@kotyのブログ

PythonとかAWSとか勉強会のこととかを、田舎者SEがつづります。記事のライセンスは"CC BY"でお願いします。

JUnitによるデータ駆動テストで困ったこと

データ駆動テストについて。Visual Studioだと、これhttp://codezine.jp/article/detail/6110?p=3にあるような感じで、データ駆動テストの記述および実行結果を確認できます。

今回JUnitでデータ駆動テストがしたかったので、まず下記のように書いてみました。

package com.mycompany.datadriven1;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import org.junit.experimental.theories.*;
import org.junit.runner.RunWith;

/**
 * 足し算するクラスをテストする
 */
@RunWith(Theories.class)
public class AppTest {

    @DataPoints
    public static Fixture[] PARAMS = {
        new Fixture(1, 4, 5),
        new Fixture(2, 5, 8), //このテストケースが失敗する
        new Fixture(3, 6, 10) //このテストケースも失敗するけど↑が通るまで失敗だと分からない
    };

    @Theory
    public void 足し算データ駆動テスト(Fixture f) {
        assertThat(f.expected, is(App.plus(f.a, f.b)));
    }

    static class Fixture {

        private final int a;
        private final int b;
        private final int expected;

        Fixture(int a, int b, int expected) {
            this.a = a;
            this.b = b;
            this.expected = expected;
        }
    }
}

しかーし、これだとテストが失敗したDataPointsの要素でテストケースの実行が止まってしまい、残りの要素が実行されません。

f:id:kkotyy:20131112231531p:plain

成功する分には問題ないのですけどね。Visual Studioだと全部実行してくれるのに。*1

最終的にこう書きました。ErrorCollectorというクラスを使います。

参考:http://stackoverflow.com/questions/8779982/why-does-junit-run-test-cases-for-theory-only-until-the-first-failure

package com.mycompany.datadriven1;

import static org.hamcrest.CoreMatchers.is;
import org.junit.*;
import org.junit.experimental.theories.*;
import org.junit.rules.ErrorCollector;
import org.junit.runner.RunWith;

/**
 * 足し算するクラスをテストする
 */
public class AppTest {

    public static Fixture[] PARAMS = {
        new Fixture(1, 4, 5),
        new Fixture(2, 5, 8), //このテストケースが失敗する
        new Fixture(3, 6, 10) //このテストケースも失敗する
    };

    @Rule
    public ErrorCollector collector = new ErrorCollector();
    
    @Test
    public void 足し算データ駆動テスト() {
        for(Fixture f:PARAMS){
            collector.checkThat(f.expected, is(App.plus(f.a, f.b)));
        }
    }

    static class Fixture {

        private final int a;
        private final int b;
        private final int expected;

        Fixture(int a, int b, int expected) {
            this.a = a;
            this.b = b;
            this.expected = expected;
        }
    }
}

f:id:kkotyy:20131112231538p:plain

これだと各要素のgreen/redにかかわらず、全ての要素をassertすることができます。

もっとええ感じにできるよ、と言う方はぜひ教えてください。

*1:よくみたらtheoryはexperimentalなんですね。experimentalだから仕方ないのか。。。