[Java][JavaScript][C#][PHP] 言語別テストの作り心地主観的比較
自己紹介
名前: sengoku
Github: sengokyu
Qiita: sengoku
子供時代 -> National JR-100でBASICを覚える
学生時代 -> SONY NEWSでunixを覚える
Visual Basicで仕事を始め、FreeBSDでサーバを立てたり、Perl/PHPでプログラム組んだりしながら今に至る。
今日話すこと
下記言語におけるテストの作り心地について話します。
- Java
- JavaScript
- C#
- PHP
Java
[Java] 用意したいもの
- NetBeansなどの統合環境
- Mavenなどの依存性管理とビルドツール
- JUnit
- Hamcrest
- Mockito
- Arquillian ← Java EEの場合
[Java] テストクラスを作る
NetBeansの場合、すでにテスト対象クラスがあるのならメニューから選ぶだけ。
[Java] このような雛形ができます
public class FooTest {
private Foo instance;
@Before
public void setUp() {
instance = new Foo();
}
@Test
public void testGetBaz() {}
}
[Java] テストメソッドの中身を作ります
String actual = instance.getBaz();
assertThat(actual, is("baz"));
[Java] 実行します
NetBeansの場合、キーボードショートカットを押すだけ。
テスト対象クラスを編集しているときも、ショートカットキーを押せば対応するテストクラスを実行してくれます。
[Java] 依存するクラスはモックにします
// モックを生成
Foo fooMock = Mockito.mock(Foo.class);
// メソッドの戻り値を設定
Mockito.doReturn("baz").when(fooMock).getBaz();
// メソッドが呼ばれたかどうかをテスト
Mockito.verify(fooMock).getBaz();
[Java] 使い心地
ショートカットキー押すだけで即実行できていい
モックの作成が簡単
JavaScript
[JavaScript] 用意したいもの
- MacかLinux。Windowsの場合はBash on Ubuntu on Windowsがいいかも
- VS CodeやEmacs等のお好みのエディタ
- Google ChromeやFirefox
- karma
- karma-jasmine
[JavaScript] テストファイルを作リます
あらかじめ決めた拡張子でファイルを作リます。
テスト対象.spec.jsが一般的???
describeで何をテストするかを書きます。
itでテスト対象がどんな動きをするのかを書きます。
[JavaScript] こんな感じになります
foo.spec.js
describe('Fooクラスのテストです', () => {
let instance;
beforeEach(() => {
instance = new Foo();
});
it('getBazするとbazが返る', () => {
});
});
[JavaScript] テストの中身を書きます
let actual = instance.getBaz();
expect(actual).toBe('baz');
[JavaScript] テストの設定ファイルを書く
- karma.conf.jsというファイルを作ります。
- 監視対象のファイル名を記載します。
- プリプロセッサが必要であれば記載します。
[JavaScript] 実行する
karmaを起動しておけば、ファイルの変更を検知して自動的にテストを実行してくれます。
[JavaScript] 依存するクラスや関数はモックにします
// モックを生成
let fooMock = jasmine.createSpyObj('Foo', ['getBaz']);
// メソッドの戻り値を設定
fooMock.getBaz.and.returnValue('baz');
// メソッドが呼ばれたかどうかをテスト
expect(fooMock.getBaz).toHaveBeenCalled();
[JavaScript] 使い心地
ファイル監視が楽チンすぎる
describeとitに日本語書けてわかりやすい
expectの書き心地が英語っぽくていい
C#
[C#] 用意したいもの
- Visual Studio (無料じゃないやつ)
- NFluent
- NSubstitute
[C#] テストプロジェクトを作ります
実プロジェクトとは別に、テスト専用の別プロジェクトを作ります。
Foo.Project なら Foo.Project.Tests みたいなのを作ります。
[C#] テストクラスを作ります
プレーンなクラスを作り、属性をつけてあげます。
[C#] こんな風になります
FooTests.cs
[TestClass]
public class FooTests
{
private Foo instance;
[TestInitialize]
public void SetUp() { instance = new Foo(); }
[TestMethod]
public void TestGetBaz() {}
}
[C#] テストメソッドの中身を書きます
var actual = instance.GetBaz();
Check.That(actual).IsEqualTo("baz");
[C#] テストを実行します
Visual Studioのメニューから、Test Explorerウィンドウを開いて、全テストを実行するか、テストを指定するかして実行します。
キーボードショートカットは、割り当ててもなぜか使えませんでした(VS2015)。つらみ
[C#] 依存するクラスはモックにします
// モックの生成
var fooMock = Substitute.For<Foo>();
// 戻り値を設定
fooMock.GetBaz().Returns("baz");
// メソッドが呼ばれたかどうかをテスト
fooMock.Received().GetBaz();
[C#] 使い心地
マウス操作するのがつらい(のは、もう過去のこと?)
モック化を阻むフレームワーク内のクラス(は、もう過去のこと?)
PHP
[PHP] 用意したいもの
- お好みのテキストエディタか統合環境
- PHPUnit
- Phake
[PHP] テストクラスを作ります
- 適当なフォルダを作成し、その中にテストクラスファイルを置きます。
- テストクラスは、\PHPUnit\Framework\TestCaseを継承しないといけません。
- テストメソッドは「test」から始まらないといけません。
[PHP] こんな風にできます
FooTest.php
class FooTest extends \PHPUnit\Framework\TestCase
{
private $instance;
public function setUp() {
$this->instance = new Foo();
}
public function testGetBaz() {}
}
[PHP] テストメソッドの中身を書きます
$actulal = $instance->getBaz();
$this->assertEquals('baz', $actual);
[PHP] テストの設定ファイルを作ります
phpunit.xmlというファイルを作成します。
phpunitの動作を設定したり、読み込むテストファイルの場所を記載します。
[PHP] テストを実行します
phpunitコマンドを実行すると、テストを実行して結果を表示してくれます。
[PHP] PHPでもモックを使いたい
// モックを生成
$fooMock = Phake::mock('Foo');
// 戻り値を設定
Phake::when($fooMock)->getBaz()->thenReturn('baz');
// 呼ばれたかどうかをテスト
Phake::verify($fooMock)->getBaz();
[PHP] 使い心地
とくに可もなく不可もなく
総合的な印象
Java
- テストを作るのが当たり前過ぎる環境が用意されています
- テストを作る/実行するストレスが少ない
- 統合テストも頑張れる
JavaScript
- テストを作るのも実行するのも流麗で気持ちいい
- 日々日々良くなっていくので、昨日の常識はdeprecateだったりします
C#
- C#言語自体はいいけれど、.Net Frameworkが絡むとつらみ
- テスト文化が後から入ってきた(?)ので、まだこなれていない印象
- .Net Core時代になれば万事解決!?
PHP
- 可もなく不可もないけれど、ちょっと楽しくない