Haxeのテストライブラリ

Haxeには様々なテストライブラリが存在しています。
下記のテスト対象クラスを参考に、それぞれどのような使い方をするのかをまとめてみました。

```hx:テスト対象クラス
class Cat {
    public function new() {}

    public function cry(): String {
        return 'にゃーん';
    }

    public function runnable(): Bool {
        return true;
    }

    public function flyable(): Bool {
        return false;
    }

    public function fly(): Void {
        trhow '猫は飛べません。';
    }
}
```


# HaxeUnit

Haxeに標準で付属しているテストライブラリ。

テストに使えるメソッドは、`assertEquals`、`assertTrue`、`assertFals`の３つのみ。
とてもシンプルに利用できますが、ちょっと複雑なケースが出てくるとテストを書くことに苦労します。

## サンプルコード

```hx:テストクラス
import haxe.unit.TestCase;
import Cat;

class Test_Cat extends TestCase {
    var cat: Cat;

    override public function setup() {
        // 初期処理をここに書く
        cat = new Cat();
    }

    override public function tearDown() {
        // 終了処理をここに書く
    }

    public function testCry() {
        assertEquals('にゃーん', cat.cry());
    }

    public function testRunnable() {
        assertTrue(cat.runnable());
    }

    public function testFlyable() {
        assertFalse(cat.flyable());
    }

    public function testFly() {
        try {
            cat.fly();
        } catch(e: String) {
            assertEquals('猫は飛べません。', e);
        }

        // `assertEquals` が呼ばれないとエラーになります。
    }
}
```

```hx:テスト設定クラス
import haxe.unit.TestRunner;
import Tset_Cat;

class Runner {
    static function main() {
        var runner = new TestRunner();

        // テストクラスを `add` メソッドを利用して追加していく。
        runner.add(new Test_Cat());

        runner.run();
    }
}
```

```hxml:コンパイル＆テスト実行（Javascriptの場合）
-main Runner
-js test.js
-cmd node test.js
```

これでテストを実行すると、下記のように出力されます。

```
Class: Test_Cat ....

OK 4 tests, 0 failed, 4 success
```

# [MassiveUnit](https://github.com/massiveinteractive/MassiveUnit/)

MassiveUnitはメタデータ駆動で、クロスプラットフォームのためのテストフレームワークだと謳っています。

クロスプラットフォームと謳っていますが、現状対応しているのは、javascript、 Flash (as2/as3)、Nekoとなっているようです。


豊富なアサーションメソッド、テストコードのスケルトンジェネレータ、カバレッジの取得などテストフレームワークとしてはそれなりに機能がそろっています。

ドキュメントが[Githubのwiki](https://github.com/massiveinteractive/MassiveUnit/wiki)にしっかりとまとまっているので、困ったら見てみると良いと思います。

## インストール

haxelibからイントール出来ます。

```
haxelib install munit
```

## 初期設定

以下のコマンドを実行してmunitを実行するための環境をセットアップします。
コマンドを実行すると、対話形式で設定項目を聞かれますが、よくわからなかったらとりあえず全部エンターキーを押して進めても問題ありません。

> ここで登録される設定項目は後ほど、`.munit`というファイルを編集することで変更することができます。

```
haxelib run munit config
```

## サンプルコード

```hx:テストクラス
import massive.munit.Assert;

class CatTest {

    var cat: Cat;

    public function new() {}

    @Before
    public function setup(): Void {
        cat = new Cat();
    }

    @Test
    public function testCry(): Void {
        Assert.areEqual('にゃーん', cat.cry());
    }

    @Test
    public function testRunnable(): Void {
        Assert.isTrue(cat.runnable());
    }

    @Test
    public function testFlyable(): Void {
        Assert.isFalse(cat.flyable());
    }

    @Test
    public function testFly(): Void {
        try {
            cat.fly();

            // 例外がスローされないとテストが成功してしまうので、ここで失敗させる。
            Assert.fail('例外が発生しない！？');
        } catch (e: String) {
            Assert.areEqual('猫は飛べません。', e);
        }
    }

}
```

```hxml:コンパイルファイル
# munitというディレクトリの中にコードがある想定
-main TestMain
-cp munit
-lib munit
-js munit/build/munit.js
```

## 実行

テスト実行前に、下記のコマンドを実行してテスト対象クラスを登録する必要があります。
ここで登録されるのは`xxxxTest.hx`という命名規則にしたがったファイルです。

```
haxelib run munit gen
```

テスト対象クラスを登録後、下記コマンドでテストを実行します。

```
haxelib run munit test
```

カバレッジを取得したい場合は、`.munit`ファイルに`classPaths=xxxx`という指定を記述し、オプションに`-coverage`を追加することで取得出来るようになります。

# [buddy](https://github.com/ciscoheat/buddy)

BDD（振る舞いを記述する）のテストフレームワーク。
自然言語に近い形式でテストを記述することが出来る。

## インストール

haxelibからインストール出来ます。

```
haxelib install buddy
```

## サンプルコード

```hx:テストクラス
import buddy.BuddySuite;

using buddy.Should;

class CatTest extends BuddySuite {

    public function new() {
        describe("Catクラス", {
            var cat: Cat;
            var call_fly: Cat -> Void;

            before({
                cat = new Cat();
                call_fly = function(cat: Cat) {
                    cat.fly();
                }
            });

            it("cryメソッドは猫の鳴き声を返すべき", {
                cat.cry().should.be("にゃーん");
            });

            it("runnableメソッドは真を返すべき", {
                cat.runnable().should.be(true);
            });

            it("flyableメソッドは偽を返すべき", {
                cat.flyable().should.be(false);
            });

            it("flyメソッドは例外を投げるべき", {
                call_fly.bind(cat).should.throwType(String);
                call_fly.bind(cat).should.throwValue("猫は飛べません。");
            });
        });
    }

}
```

```hx:テスト定義クラス
import buddy.Buddy;

// Buddyのジェネリック型にテストクラスを記述していく
class Test implements Buddy<[CatTest]> {}
```

```hxml:コンパイルファイル
-main Test
-lib buddy
--interp
```

## 実行

テストクラスをコンパイルすればテストが実行されます。

```
haxe test.hxml
```

テストの書き方にもよりますが、テスト結果が分かりやすく出力されるのがいいですね（分かりやすいと思えるかは個人差あり）。

```出力結果
Catクラス
  cryメソッドは猫の鳴き声を返すべき (Passed)
  runnableメソッドは真を返すべき (Passed)
  flyableメソッドは偽を返すべき (Passed)
  flyメソッドは例外を投げるべき (Passed)
4 specs, 0 failures, 0 pending
```

---

ここまで、３つのテストライブラリについて紹介してみました。
Haxeでは、言語の知名度の割にかなりの数のテストライブラリが乱立しています。
ここでは紹介しきれませんでしたが、興味があれば下記リンクから色々なテストライブラリを探してみると面白いですよ。

http://lib.haxe.org/search/?v=test