なぜ今アサーション?
現時点でJUnit5ではHamcrestのMatcherは提供せず、使用者が自由に選択する方針で進んでいます。
そうなった場合、標準でサポートされるassertTrueやassertEquelsなどだけでは、ちょっと頼りなく車輪の再発明になりそうなので、候補になりそうなHamcrestとAssertJのよく使いそうなメソッド比較表を作りました。
Google Truthも気になるところなので、時間があれば追加しようと思います。
尚、FESTは現時点で更新がストップしているようなので候補から除外しています。
アサーションライブラリ
Hamcrest
Junit4で標準採用されているアサーションライブラリ。
知名度や採用実績では言うまでもなく一番だと思います。
public class HamcrestTest {
List<String> list = Arrays.asList("hoge", "fuga", "piyo");
@Test
public void test() {
assertThat(true, is(true));
assertThat("hoge", is("hoge"));
assertThat(list, is(not(empty())));
assertThat(list, is(contains("hoge", "fuga", "piyo")));
}
}
AssertJ
"Fluent assertions for java"と謳っているとおり、メソッドチェインでアサーション処理を記述できます。
またJava 8対応、外部ライブラリ連携、容易なカスタムアサーション生成など多くの機能にも対応しています。
public class AssertJTest {
List<String> list = Arrays.asList("hoge", "fuga", "piyo");
@Test
public void test() {
assertThat(true).isTrue();
assertThat("hoge").isEqualTo("hoge");
assertThat(list).isNotEmpty()
.contains("hoge", "fuga", "piyo");
}
}
見た目はHamcrestとあまり変わらないように感じますが、大きなメリットはFluent APIのため、チェック対象の型情報からIDE補完で使用可能なメソッド一覧を選択できることです。
このため、Hamcrestのように事前にAPIを把握していなくても、型安全性を維持したまま直感的にチェック処置が記述可能です。(例えば、isTrueはチェック対象がboolean、containsはコレクションや配列などの場合にのみ候補になる)
Truth
Google Guavaのテストコードなどにも使われているアサーションライブラリ。
直感的なエラーメッセージや、拡張性に違いはありますがAssertJやFESTから影響を受けているため非常に似たインターフェイスとなっています。
メソッド比較
|機能| Hamcrest | AssertJ |
|:--|:--|:--|:--|
|チェック対象を指定する|assertThat|assertThat|assertThat|
|Trueであることをチェックする| is |isTrue||
|Falseであることをチェックする| is |isFalse||
|同じ値であることをチェックする|is| isEqualTo ||
|同じ値でないことをチェックする|is + not|isNotEqulTo||
|nullであることをチェックする|is + nullValue | isNull ||
|nullでないことをチェックする|is + notNullValue | isNotNull ||
|compareTo() で比較する| is + comparesEqualTo | isEqualByComparingTo ||
|同じインスタンスであることをチェックする|is + sameInstance | isSameAs ||
|指定したクラスのインスタンス型であることをチェックする|is + instanceOf | isInstanceOf ||
|toString() で比較する|is + hasToString | hasToString ||
|指定した文字で始まることをチェックする|is + startsWith | startsWith ||
|指定した文字で終わることをチェックする|is + endsWith | endsWith ||
|指定した文字が含まれることをチェックする|is + containsString | contains ||
|大文字・小文字を区別せずに比較する|is + equalToIgnoringCase | isEqualToIgnoringCase ||
|大文字・小文字・ブランク文字を無視して比較する|is + equalToIgnoringWhiteSpace |isEqualToIgnoringWhitespace ||
|空文字であることをチェックする| isEmptyString | isEmpty ||
|空文字または null であることをチェックする| isEmptyOrNullString | isNullOrEmpty ||
|正規表現を使ってチェックする|-| matches ||
|数値であることをチェックする|-| containsOnlyDigits ||
|行数をチェックする|-| hasLineCount ||
|指定した順序で文字列が現れることをチェックする| is + stringContainsInOrder | containsSequence ||
|指定した範囲の値であることをチェックする| is + closeTo | isBetween ||
|指定した値より大きいことをチェックする|is + greaterThan | isGreaterThan ||
|指定した値以上であることをチェックする|is + greaterThanOrEqualTo | isGreaterThanOrEqualTo ||
|指定した値より小さいことをチェックする|is + lessThan | isLessThan ||
|指定した値以下であることをチェックする|is + lessThanOrEqualTo | isLessThanOrEqualTo ||
|全ての要素が等しいことをチェックする| is + contains | contains ||
|指定した要素を持つことをチェックする| hasItem | containsOnly ||
|指定した要素を全て含むことをチェックする| hasItems | containsOnly ||
|指定したサイズであることをチェックする| hasSize | hasSize ||
|空であることをチェックする|is + empty | isEmpty ||
|空の Iterator であることをチェックする| is + emptyIterable |isEmpty||
|指定したエントリを持つことをチェックする| hasEntry | containsEntry ||
|指定したキーを持つことをチェックする| hasKey | containsKey ||
|指定した値を持つことをチェックする| hasValue | containsValue ||
|指定したプロパティを持つことをチェックする| hasProperty | filteredOn ||
|全てのプロパティが等しいことをチェックする|is + samePropertyValuesAs |isEqualToComparingFieldByField||
|定した要素と配列の要素が全て等しいことをチェックする|is + arrayContaining | containsExactly ||
|順序を無視して、指定した要素が全て配列に含まれることをチェックする|is + arrayContainingInAnyOrder | contains ||
|配列のサイズをチェックする|is + arrayWithSize |hasSize||
|配列が空であることをチェックする|is + emptyArray |isEmpty||
|配列の中に指定した値が存在することをチェックする| hasItemInArray | contains ||
|テストに失敗したときのメッセージを上書きする| describedAs | as ||
まとめ
個人的には、IDE補完が効くことや、コレクション、配列など同系統の処理のインターフェイスが統一されているなどAssertJの方が使いやすい印象です。
新規のライブラリは、その学習コストが問題になりがちですが、現状Hamcrestをバリバリ使いこなしているチームでないかぎり、AssertJはIDE補完から選択できるので、同様の機能が容易に使えます。
また、カスタムアサーションやJava 8対応、外部ライブラリ連携など柔軟性、機能性共に高いところも魅力です。
JUnit5からだけでなく、JUnit4からでも十分採用する価値はあると思います。
参考
HamcrestのMatchersに定義されているメソッドの使い方メモ
AssertJ版:テストでよく使う検証メソッド一覧