JUnit API探訪:Assertクラス/assertThatメソッド

JUnitをより深く知っていこう。と言う事で本丸JUnitのクラスから幾つか機能を探訪していこうかと思います。

org.junit.Assertクラス

主なメソッドは以下の通り。

メソッド 説明
assertArrayEquals(arrays expected, arrays actual) 配列同士を比較、イコールである場合true
assertEquals(Object expected, Object actual) オブジェクト同士を比較、イコールである場合true
assertFalse(boolean condition) 条件がfalseである事を検証、falseの場合true
assertNotNull(Object obj) オブジェクトがNullで無いことを検証、Nullでない場合true
assertNotSame(Object expected, Object actual) expected != actualの場合true
assertNull(Object obj) オブジェクトがNullである事を検証、Nullの場合true
assertSame(Object expected, Object actual) expected == actualの場合true
assertTrue(boolean condition) 条件がtrueである事を検証、trueの場合true
assertThat([value], [matcher statement]) 汎用的な比較を許可するアサーションメソッド
fail() 常に失敗させる。『ここに来たらアカン(テスト失敗)』箇所に配置

assertEqualsとassertSameについて、違いを調べてみる。

assertEqualsで事足りそうだし、assertSameを好んで使うという場面はそんなに無さげなのかな〜。

assertThatメソッド

Assertクラスのメソッドの1つ、assertThatメソッドについてはより範囲が広く、機能も多いので別途深掘り。assertThatに関しては以下のエントリ群が詳しいです。

assertThatで使うMatcherに関しては、APIをざっと眺めるだけでても幾つか用意されているようです。

allOf
any
anyOf
anything
describedAs
equalsTo
instanceOf
is
not
notNullValue
nullValue
sameInstance
both
containsString
either
everyItem
hasItem
hasItems

org.hamcrest.Matchersのメソッド一覧

そしてこれらとは別にorg.hamcrest.Matchersというクラスも存在。これが一番提供メソッドも多いようなので今回はこちらのクラスメソッド群について色々写経しつつ、機能・概要を把握して行く事にする。(※このライブラリに関するJavadoc APIを見たほうが手っ取り早いと思ったんだけど、サイト経由では公開されてるJavadoc APIは確認出来ず。何でだろ?)


ざっくり用途・機能で分けつつ、写経したソースコードも一緒にUPしときます。振り分け的に怪しいのもあるかもしれないけどそこは御容赦を。

参考:

条件制御
allOf すべてのMatcher条件が一致するかどうか
anyOf いずれかのMatcher条件が一致するかどうか
anything 何にでもマッチする
both AND条件を構成
either OR条件を構成
describedAs 検証条件の詳細を記述
is 条件(である)
not 条件(でない)
  • allOf:全てのMatcher条件が一致するかどうかを検証
@Test
public void checkAllOf() {
	// 全てのMatcher条件が一致していればOK
	assertThat(
		"HelloWorld",
		allOf(
			is("HelloWorld"),
			notNullValue(),
			startsWith("Hello")
		)
	);
}
  • anyOf:いずれかのMatcher条件が一致していればOK
@Test
public void checkAnyOf() {
	// いずれかのMatcher条件が一致していればOK
	assertThat(
		"HelloWorld",
		anyOf(
			is("HelloWorld!!!"),
			nullValue(),
			startsWith("Hello")
		)
	);
}
  • anything:何にでも一致
@Test
public void checkAnything() {
	// 何でも一致
	assertThat("Java", anything());
}
  • both:AND条件を構成
  • either:OR条件を構成
@Test
public void checkBothAndEither() {
	// both A and B
	assertThat("java", both(startsWith("j")).and(endsWith("a")));
	// either A or B
	assertThat("java", either(startsWith("j")).or(startsWith("g")));
}
  • describedAs:検証条件の詳細を記述
@Test
public void checkDescribedAs() {
	// 一致しない場合、"Expected: start with J  but: was "XXXX"となる
	String text = "Java";
	assertThat(text, describedAs("start with J", startsWith("J")));
}
  • is:条件(である)
  • not:条件(でない)
// この後のコードで沢山出てくるのでここでのコードは割愛
オブジェクト・型検証に関するもの
any 引数に取った型のクラスなら何でも良い、という指定を行う場合に使う(※instanceofのエイリアス)
equalTo 比較(一致していること)
instanceOf オブジェクトの型を検証
isA 型のマッチング検証に用いる
notNullValue 条件(Nullではない)
nullValue 条件(Nullである)
sameInstance インスタンスの同一性を検証
  • any:引数に取った型のクラスなら何でも良い、という指定を行う場合に使う(※instanceofのエイリアス)
@Test
public void checkAny() {
	// any は instanceof のエイリアス。クラス型が合ってれば良い
	assertThat("Java", is(any(String.class)));
	assertThat(1, is(any(Integer.class)));
	assertThat(10, is(any(Object.class)));
}
  • equalTo:比較(一致していること)
	// 比較
	assertThat(100, equalTo(100));
	assertThat("foo", equalTo("foo"));
	assertThat(new String[] {"foo", "bar"}, equalTo(new String[] {"foo", "bar"}));
  • instanceOf:オブジェクトの型を検証
@Test
public void checkInstanceof() {
	// インスタンスの型を確認
	assertThat("Java", is(instanceOf(String.class)));
}
  • isA:型のマッチング検証に用いる
@Test
public void checkISA() {
	// 型のマッチング検証
	assertThat(new Date(), isA(Date.class));
	assertThat("java", is(any(String.class)));
	assertThat(10000, is(instanceOf(Integer.class)));
}
  • notNullValue:Nullではない
  • nullValue:Nullである
	assertThat("java", notNullvalue);
	assertThat(null, nullvalue);
@Test
public void checkSameInstance() {
	// インスタンスの同一性を検証
	Boolean flag = false;
	assertThat(flag, sameInstance(Boolean.FALSE));
	String text = "string";
	assertThat(text, sameInstance("string"));
}
文字列検証に関するもの
containsString 文字要素を含むかどうかを検証
endsWith 指定の文字列で終わっていることを検証
equalToIgnoringCase 比較(文字列:大文字小文字の違いを無視)
equalToIgnoringWhiteSpace 比較(文字列:大文字小文字の違い、更には空白文字も無視)
hasToString toStringの内容を明示的に比較
isEmptyOrNullString 文字列が空もしくはNullである事を検証
isEmptyString 文字列が空である事を検証
startsWith 指定の文字列で始まっている事を検証
stringContainsInOrder 文字列の中に文字列(配列要素)が含まれているかどうかを検証
  • containsString : 文字要素を含むかどうかを検証
	// 指定した文字列を含んでいるか
	assertThat("この先生きのこるために", is(containsString("きのこ")));
  • startsWith:指定の文字列で始まっている事を検証
  • endsWith:指定の文字列で終わっていることを検証
	assertThat("java", both(startsWith("j")).and(endsWith("a")));
	assertThat("java", either(startsWith("j")).or(startsWith("g")));
  • equalToIgnoringCase:比較(文字列:大文字小文字の違いを無視)
  • equalToIgnoringWhiteSpace:比較(文字列:大文字小文字の違い、更には空白文字も無視)
	// 比較(大文字小文字の違いを無視)
	assertThat("JUNITTESTCASE", is(equalToIgnoringCase("JUnitTestCase")));
	// 比較(大文字小文字の違い・前後の空白(半角・全角)を無視
	assertThat("  JAVASCRIPT ", is(equalToIgnoringWhiteSpace("Javascript")));
	// 比較(間にある空白は無視してくれないらしい)
	assertThat("  JAVA SCRIPT ", is(not(equalToIgnoringWhiteSpace("Javascript"))));
  • hasToString:toStringの内容を明示的に比較
	// toStringの内容を明示的に比較検証
	List<Integer> list = new ArrayList<Integer>();
	list.add(111);
	list.add(222);
	list.add(333);
	assertThat(list.toString(), is(hasToString("[111, 222, 333]")));
	assertThat(new Object(), is(hasToString(startsWith("java.lang.Object@"))));
  • isEmptyOrNullString:文字列が空もしくはNullである事を検証
	// 文字列が空もしくはNullである事を確認
	String nullString = null;
	assertThat(nullString, isEmptyOrNullString());
	String emptyString = "";
	assertThat(nullString, isEmptyOrNullString());
  • isEmptyString:文字列が空である事を検証
	// 文字列が空である事を確認
	assertThat(emptyString, isEmptyString());
	assertThat(nullString, not(isEmptyString()));
  • stringContainsInOrder:文字列の中に文字列(配列要素)が含まれているかどうかを検証
	// assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("bar", "foo")))
	// 文字列の中に文字列群が存在するかを確認(所定の順番で存在している必要がある)
	assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("foo", "bar")));
	assertThat("myfoobarbaz", not(stringContainsInOrder(Arrays.asList("bar", "foo"))));
	assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("myfoo", "foobar")));
	assertThat("myfoobarbaz", stringContainsInOrder(Arrays.asList("foobar", "foobar")));
	assertThat("myfoobarbaz", not(stringContainsInOrder(Arrays.asList("foobar", "yfoob"))));
数値検証に関するもの
closeTo 数値期待値の検証
comparesEqualsTo 数値比較(同値)
greaterThan 数値比較(より大きい)
greaterThanOrEqualTo 数値比較(以上)
lessThan 数値比較(未満)
lessThanOrEqualTo 数値比較(以下)
  • closeTo :数値期待値の検証
	// 期待値の範囲内かどうかを検証
	assertThat(10.2, is(closeTo(10, 0.3)));
  • comparesEqualsTo:数値比較(同値)
	// 数値比較(equal)
	assertThat(new BigDecimal("1000"), comparesEqualTo(new BigDecimal(1000)));
  • greaterThan:数値比較(より大きい)
  • greaterThanOrEqualTo:数値比較(以上)
	// 数値比較(greaterThan)
	assertThat(10, is(greaterThan(9)));
	assertThat(10, is(greaterThanOrEqualTo(10)));
	assertThat(10, is(greaterThanOrEqualTo(9)));
  • lessThan:数値比較(未満)
  • lessThanOrEqualTo:数値比較(以下)
	// 数値比較(lessThan)
	assertThat(100.02, is(lessThan(101.03)));
	assertThat(100, is(lessThanOrEqualTo(101)));
	assertThat(100, is(lessThanOrEqualTo(100)));
配列検証に関するもの
array 配列要素を比較、検証する際に構成要素として用いる
arrayContaining 配列内容・順序が一致しているかどうか
arrayContainingInAnyOrder 配列内容が一致しているかどうか(順序は問わない)
arrayWithSize 配列のサイズを確認
emptyArray 配列要素が空である事を検証
hasItemInArray 配列内に所定の要素を含むかどうか確認
  • array:配列要素を比較、検証する際に構成要素として用いる
@Test
public void checkArray() {
	// 配列要素を比較、検証する際に構成要素として用いる。
	// 値が異なる場合、配列要素インデックス及び異なった値がbutの詳細情報として表示される
	assertThat(
		new String[]{"Java", "Groovy", "Scala"},
		is(array(
			is("Java"),
			is(startsWith("G")),
			notNullValue()
		)));
}
  • arrayContaining:配列内容・順序が一致しているかどうか
  • arrayContainingInAnyOrder:配列内容が一致しているかどうか(順序は問わない)
  • arrayWithSize:配列のサイズを確認
@Test
public void checkArrayContaining() {
	String[] actual = {"100", "200", "300", "400"};
	// arrayContaining: 配列の内容・順序が一致しているかどうか
	assertThat(actual, arrayContaining("100", "200", "300", "400"));
	// arrayContainingInAnyOrder: 配列の内容が一致しているかどうか(順序は問わない)
	assertThat(actual, arrayContainingInAnyOrder("400", "100", "300", "200"));
	// arrayWithSize: 配列のサイズを確認
	assertThat(actual, arrayWithSize(4));
	assertThat(actual, not(arrayWithSize(5)));
}
  • emptyArray:配列要素が空である事を検証
	// 配列要素が空である事を確認
	String[] actualStringArray = new String[0];
	assertThat(actualStringArray, is(emptyArray()));
	String[] actualStringArray2 = new String[3];
	assertThat(actualStringArray2, is(not(emptyArray())));
  • hasItemInArray :配列内に所定の要素を含むかどうか確認
	// 配列内に所定の要素を含むかどうか確認
	String[] stringsArray = {"scrum", "agile", "xp"};
	assertThat(stringsArray, hasItemInArray("agile"));
コレクション検証に関するもの
contains コレクション要素が指定通りの順番で一致しているか検証
containsInAnyOrder コレクション要素が一致しているかを検証(順番は問わない)
empty コレクション要素が空であることを検証
emptyCollectionOf 所定の型で構成された空のコレクションで有ることを検証
emptyIterable コレクションから得られるiteratorが空である事を検証
emptyIterableOf iteratorの型を確認しつつ、空である事を検証
hasItem コレクション内に所定の要素を含むかどうか検証
hasItems コレクション内に所定の要素(複数指定可能)を含むかどうか検証
hasSize コレクションのサイズを検証
isIn コレクションに所定の要素を含むかどうか検証
isOneOf コレクションに所定の要素を含むかどうか検証
iterableWithSize サイズを検証
  • contains:コレクション要素が指定通りの順番で一致しているか検証
  • containsInAnyOrder:コレクション要素が一致しているかを検証(順番は問わない)
	List<String> actual = new ArrayList<>();
	actual.add("Java");
	actual.add("Groovy");
	actual.add("Scala");
	// 指定の順番通りにコレクション要素が一致しているか
	String[] expected = {"Java","Groovy","Scala"};
	assertThat(actual, is(contains(expected)));
	// コレクション要素が一致しているか(順番は問わない)
	String[] expectedInAnyOrder = {"Groovy","Scala","Java"};
	assertThat(actual, is(containsInAnyOrder(expectedInAnyOrder)));
  • empty:コレクション要素が空であることを検証
@Test
public void checkEmptyCondition() {
	// コレクション要素が空である事を検証
	List<Integer> actual = new ArrayList<Integer>(); 
	assertThat(actual, is(empty()));
	actual.add(10);
	assertThat(actual, not(empty()));
}
  • emptyCollectionOf:所定の型で構成された空のコレクションで有ることを検証
  • emptyIterable:コレクションから得られるiteratorが空である事を検証
  • emptyIterableOf:iteratorの型を確認しつつ、空である事を検証
	//assertThat(new ArrayList&lt;String&gt;(), is(emptyCollectionOf(String.class)))
	// 所定の型で構成された空のコレクションで有ることを検証
	List<BigDecimal> actualList = new ArrayList<BigDecimal>();
	assertThat(actualList, is(emptyCollectionOf(BigDecimal.class)));

	// assertThat(new ArrayList&lt;String&gt;(), is(emptyIterable()))
	// コレクションから得られるIteratorが空である事を確認
	assertThat(actualList, is(emptyIterable()));
	List<String> stringList = new ArrayList<String>();
	assertThat(stringList, is(emptyIterable()));

	// Iteratorの型を確認しつつ、空である事を確認
	assertThat(actualList, is(emptyIterableOf(BigDecimal.class)));
	assertThat(stringList, is(emptyIterableOf(String.class)));
  • hasItem:コレクション内に所定の要素を含むかどうか検証
  • hasItems:コレクション内に所定の要素(複数指定可能)を含むかどうか検証
  • hasSize:コレクションのサイズを検証
  • isIn:コレクションに所定の要素を含むかどうか検証
  • isOneOf:コレクションに所定の要素を含むかどうか検証
	// コレクション内に所定の要素を含むかどうか確認
	List<String> stringList = new ArrayList<String>();
	stringList.add("perl");
	stringList.add("php");
	stringList.add("python");
	assertThat(stringList, hasItem("php"));
	assertThat(stringList, hasItems("perl", "python"));
	assertThat(stringList, hasItems("perl"));
	// コレクションのサイズを検証
	assertThat(stringList, hasSize(3));

	// コレクション内に要素を含むかどうか確認
	assertThat("php", isIn(stringList));
	assertThat("php", isOneOf("php", "perl", "python"));
Map検証に関するもの
hasEntry Mapオブジェクトに所定のkey-valueエントリが含まれているかを検証
hasKey Mapオブジェクトに所定のkeyが含まれているかを検証
hasValue Mapオブジェクトに所定のvalueが含まれているかを検証
@Test
public void checkMaps() {
	Map<Integer, String> actualMap = new HashMap<Integer, String>();
	actualMap.put(1, "Java");
	actualMap.put(2, "Groovy");
	actualMap.put(3, "Scala");
		
	assertThat(actualMap, hasEntry(2, "Groovy"));
	assertThat(actualMap, hasKey(3));
	assertThat(actualMap, hasValue("Java"));
}
Bean要素検証に関するもの
hasProperty Bean要素に所定のプロパティが存在するかどうかを検証
samePropertyValuesAs Beanのプロパティ値の内容を検証
public class Person {
	private String name;
	private int age;
	private String address;

	// setter, getterは割愛
	// Bean要素に所定のプロパティが存在するか確認
	Person person = new Person();
	assertThat(person, hasProperty("name"));
	assertThat(person, hasProperty("age"));
	assertThat(person, hasProperty("address"));
	assertThat(person, not(hasProperty("mail")));

	// プロパティの値を比較
	Person personActual = new Person();
	personActual.setName("すずきいちろう");
	personActual.setAge(39);
	personActual.setAddress("N.Y");
	Person personExpected = new Person();
	personExpected.setName("すずきいちろう");
	personExpected.setAge(38);
	personExpected.setAddress("N.Y");
	assertThat(personActual, is(samePropertyValuesAs(personExpected)));
その他

その他上記で分類しきれなかったものなどを列挙。まぁ力尽きたとも言うが…w いずれ対応出来れば。

eventFrom Eventオブジェクト関連のメソッド
eventItem Eventオブジェクト関連のメソッド
hasXPath XMLドキュメントの検証用
theInstance  
typeCompatibleWith  


ふぅ…これだけ量があると概要把握するだけでも時間掛かりますわな。でもassertThatメソッド、これだけ機能が豊富で表現も豊かであれば、だいぶ便利に使えますな。引き続きJUnit APIについては興味深いところから学んで行こうと思います。


【追記】:このエントリを受けて、いろふさんが新たにエントリを書いてくれていた。やっぱりJavadoc無かったのか〜。その他諸々も勉強になります。