web-dev-qa-db-ja.com

従来のassertXXX()-Methodsの代わりにHamcrest-MatcherとassertThat()を使用する理由

AssertクラスJavaDocの例を見ると

_assertThat("Help! Integers don't work", 0, is(1)); // fails:
// failure message:
// Help! Integers don't work
// expected: is <1> 
// got value: <0>
assertThat("Zero is one", 0, is(not(1))) // passes
_

assertEquals( 0, 1 )のような大きな利点は見当たりません。

コンストラクトがより複雑になった場合、メッセージにとってはいいかもしれませんが、より多くの利点がありますか?読みやすさ?

148
Peter Paul

意図に完全に一致するassertFooが存在する場合には、大きな利点はありません。それらの場合、それらはほぼ同じように動作します。

ただし、多少複雑なチェックを行うと、その利点がより明確になります。

assertTrue(foo.contains("someValue") && foo.contains("anotherValue"));

vs.

assertThat(foo, hasItems("someValue", "anotherValue"));

どちらが読みやすいかについては説明できますが、アサートが失敗すると、assertThatから適切なエラーメッセージが表示されますが、assertTrueからは最小限の情報しか取得できません。

assertThatは、アサーションが何であり、代わりに何を取得したかを示します。 assertTrueは、falseを期待した場所でtrueを得たことだけを通知します。

168
Joachim Sauer

JUnit リリースノート バージョン4.4(導入された場所)には、次の4つの利点があります。

  • より読みやすく、入力しやすい:この構文により、assertEqualsではなく、件名、動詞、オブジェクト(assert "x is 3")の観点から考えることができます。動詞、オブジェクト、件名を使用します(「3に等しい」をアサート)
  • 組み合わせ:任意のマッチャーステートメントを否定(not(s))、組み合わせ(either(s)) or(t))、コレクションにマッピング(each(s))、またはカスタムの組み合わせで使用( afterFiveSeconds(s)
  • 読み取り可能な障害メッセージ。 (...)
  • カスタムマッチャー。 Matcherインターフェースを自分で実装することにより、独自のカスタムアサーションに対して上記の利点をすべて得ることができます。

新しい構文を作成した人からのより詳細な議論: here

45
Manur

基本的にコードの可読性を高めるために

ハムクレストに加えて、 fest assertions も使用できます。これらには、hamcrestよりもいくつかの利点があります

いくつかの例

import static org.fest.assertions.api.Assertions.*;

// common assertions
assertThat(yoda).isInstanceOf(Jedi.class);
assertThat(frodo.getName()).isEqualTo("Frodo");
assertThat(frodo).isNotEqualTo(sauron);
assertThat(frodo).isIn(fellowshipOfTheRing);
assertThat(sauron).isNotIn(fellowshipOfTheRing);

// String specific assertions
assertThat(frodo.getName()).startsWith("Fro").endsWith("do")
                           .isEqualToIgnoringCase("frodo");

// collection specific assertions
assertThat(fellowshipOfTheRing).hasSize(9)
                               .contains(frodo, sam)
                               .excludes(sauron);


// map specific assertions (One ring and elves ring bearers initialized before)
assertThat(ringBearers).hasSize(4)
                       .includes(entry(Ring.oneRing, frodo), entry(Ring.nenya, galadriel))
                       .excludes(entry(Ring.oneRing, aragorn));

2016年10月17日更新

Festはもうアクティブではありません。代わりに AssertJ を使用してください。

38
Igor Popov

非常に基本的な正当化は、新しい構文を台無しにするのが難しいということです。

テスト後、特定の値fooが1であると仮定します。

assertEqual(1, foo);

- または -

assertThat(foo, is(1));

最初のアプローチでは、正しい順序を忘れて逆方向に入力するのは非常に簡単です。次に、1を予期して2を取得したためにテストが失敗したと言うのではなく、メッセージは逆向きです。テストに合格しても問題はありませんが、テストが失敗すると混乱を招く可能性があります。

2番目のバージョンでは、この間違いを犯すことはほぼ不可能です。

18
Andy Davis

例:

assertThat(5 , allOf(greaterThan(1),lessThan(3)));
//  Java.lang.AssertionError:
//  Expected: (a value greater than <1> and a value less than <3>)
//       got: <5>
assertTrue("Number not between 1 and 3!", 1 < 5 && 5 < 3);
//  Java.lang.AssertionError: Number not between 1 and 3!
  1. テストをより具体的にすることができます
  2. テストが失敗すると、より詳細な例外が発生します
  3. テストを読みやすくする

btw:assertXXXにテキストを書くこともできます...

9
MartinL
assertThat(frodo.getName()).isEqualTo("Frodo");

自然言語に近い。

読みやすく、分析しやすいコード。プログラマは、新しいコードを書くよりもコードの分析に多くの時間を費やします。したがって、コードの分析が容易な場合、開発者の生産性は向上するはずです。

追伸コードはよく書かれた本であるべきです。自己文書化されたコード。

3
user4515828

assertThatにはassertEqualsよりも利点があります-
1)より読みやすい
2)失敗に関する詳細情報
3)コンパイル時エラー-実行時エラーではなく
4)テスト条件の記述の柔軟性
5)ポータブル-hamcrestを使用している場合、基盤となるフレームワークとしてjUnitまたはTestNGを使用できます。

1
samshers