JUnit4.11がリリースされていたので、リリースノートを和訳してみました

JUnit4.11がリリースされていたので、リリースノートを和訳してみました。
新機能紹介です。
https://github.com/KentBeck/junit/blob/master/doc/ReleaseNotes4.11.md

個人的にはParameterized Testsの各テストに名前をつけれるようになる機能が一押しです。テストの実行結果が圧倒的に見やすくなります。各機能の詳細についてはまた機会があれば書きたいと思います。

和訳がひどいのは…すみません。間違っていればバシバシ指摘していただければ幸いです。
原文の方が読みやすいかもしれません。orz


Summary of changes in version 4.11

Matchers : Hamcrest1.3にアップグレード

JUnitは今回のバージョンアップで、最新バージョンのHamcrestを使用するようになりました。これにより、現在存在するすべてのMatcherを利用できるようになりました。 また、アサーションが失敗した場合に、ミスマッチの説明が表示されるように改善されたassertThatのメリットも教授することができます。

Example

assertThat(Long.valueOf(1), instanceOf(Integer.class));
Old error message:

Expected: an instance of java.lang.Integer
     got: <1L>
New error message:

Expected: an instance of java.lang.Integer
     but: <1L> is a java.lang.Long

さらに、Hamcrestの新しいFeatureMatcherによって、カスタマイズされたミスマッチの説明を使用する、カスタムMtcherの作成がとても簡単になります。


@Test
public void featureMatcher() throws Exception {
    assertThat("Hello World!", length(is(0)));
}

private Matcher<String> length(Matcher<? super Integer> matcher) {
    return new FeatureMatcher<String, Integer>(matcher, "a String of length that", "length") {
        @Override
        protected Integer featureValueOf(String actual) {
            return actual.length();
        }
    };
}

このテストを実行すると、以下のような失敗のメッセージが返されます。


Expected: a String of length that is <0>
     but: length was <12>

JUnitMatchersのほとんどのマッチャーは非推奨になています。CoreMatchersを直接使ってください。

Parameterized Tests

Parameterized テストにおいて、各々のテストケースを簡単に識別するために、@Parametersアノテーションを用いて、名前をつけられるようになりました。名前には、実行時に置き換えられるプレースホルダーを含めることができます。

{index}: 現在のパラメーターインデックス

{0}, {1}, …: 一番目、二番目、・・・のパラメーターの値

Example

@RunWith(Parameterized.class)
public class FibonacciTest {

    @Parameters(name = "{index}: fib({0})={1}")
    public static Iterable<Object> data() {
        return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
                { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
    }

    private int input;
    private int expected;

    public FibonacciTest(int input, int expected) {
        this.input = input;
        this.expected = expected;
    }

    @Test
    public void test() {
        assertEquals(expected, Fibonacci.compute(input));
    }
}

この例の中では、Parameterized runnerは[1:fib(3)=2]というような名前を生成します。
もし、名前を指定しない場合、現在のパラメーターインデックスがデフォルトで使用されます。

テストの実行順序

Junitはテストメソッドの実行順序を指定しないようにデザインされています。いままでは、メソッドは単純に、リフレクションAPIによって得られる順序で実行されていました。しかし、JVMに依存する順番を使うことは、あまり賢い方法とはいえません。なぜなら、Java プラットフォームは特定の順序を指定していないからです。実際にJDK7においては、多少順序がランダムになります。もちろん、正しくかかれたテストコードは順序を前提としていないはずですが、いくつかは異なるものもあるでしょう。予測可能な失敗は、特定の環境でランダムに発生する失敗よりもましでしょう。

今後、JUnitはデフォルトで、常に一定ではあるが、予測可能ではない順序を使用します。(MethodSorters.DEFAULT)テストの実行順序を変えたい場合は、テストクラスに@FixMethodOrderアノテーションをつけ、有効なMethodSortersを指定するだけです。

@FixMethodOrder(MethodSorters.JVM): テストメソッドの実行順序をJVMによって決められる順番のままにします。この順序は実行毎に変わる可能性があります

@FixMethodOrder(MethodSorters.NAME_ASCENDING): テストメソッドをメソッドの名前でソートします。辞書式順序です。

Maven artifacts

現在のところ、JUnitには二つのMavenアーティファクトがあります。Junit:junit-depとjunit:junitです。Mavenの観点から言えば、前者だけが意味をなしていました。なぜなら、Hamcrestのクラスを含んでおらず、HamcrestのMavenアーティファクトへの依存が宣言されているためです。後者は、Hamcrestのクラスを含んでおり、これは、まったくMavenらしくはありません。

このリリース以後、皆さんはjunit:junitを使用すべきです。これは以前はjunit:junit-depでした。もし、junit:junit-depへの参照を続けた場合、Mavenは自動的に新しいjunit:junitに置き換え、それを直すよう警告を表示します。

Rules

Rulesに対しては、かなりの量の改善がなされました。 MethodRuleは非推奨となりました。
@Ruleと@ClassRuleは両方ともTestRuleを返り値とするメソッドに使用することができます。
ExpectedException は失敗したケースでは、常に実際の例外のスタックトレースを表示します。
TemporaryFolderが、親フォルダを指定できるようになりました。加えて、newFile/newFolderメソッドは、ファイルやフォルダが作成できなかったときには、失敗します。
TestWatcherはskippedと呼ばれる新しいテンプレートメソッドを持っています。それは、テストがassumptionの失敗によってスキップされたときに実行されます。

Improvements to Assert and Assume

assertNotEqualsがAssertに追加されました。
assertEqualsのオーバーロードされたメソッドが追加され、二つのフロートが与えられた誤差の範囲で等しいかをチェックできるようになりました。
Assumeにあるほとんどのメソッドにカスタムメッセージが渡せるようになりました。

コメント

師子乃 さんの投稿…
こんにちは。

歴史を感じますね。