読者です 読者をやめる 読者になる 読者になる

こいばな - riskriskと時々鼻メガネ -

正式名称は「どすこい!鼻メガネ会長のいつでも土俵際!」です。ソフトウェア開発に関することを書いています。

JUnitのassert

最近Javaで開発してるので、Junitつかってテスト書いてるんですが
assertの種類を理解してなかったので、テストコードを作成してみました。

Junitのテストクラスに直接突っ込めば動きます。
ちなみにAndroid上で動かしてたのでLogクラスを一部使ってます。
Androidじゃないところで動かすなら、適当にSystem.out.printlnあたりに書き換えてください

やってみて興味深かったのは、assertEqualsでオブジェクトの比較を行う場合に
expect側のequalsが使われるという事。
継承されたクラスで比較するときに、この辺りに手が入ってると面倒なことがあるかも?

C++だと、文字列みたいな良く比較するようなオブジェクトは、
==演算子オーバーロードされてて、普通に比較できるので
equalsに違和感あるんだよなぁ
(最初==で比較できると思っていてドハマりしたのは内緒です)

以下、Assertのテストプログラム

public void testAssert() {

	// プリミティブ型は、そのまま使える
	assertEquals(true, true);
	assertEquals((int)1, (int)1);

	// オブジェクトは、equalsで比較される
	assertEquals(
			new Object() {
				@Override
				public boolean equals(Object o) {
					Log.d(TAG, "call lhs equals.");
					return true;
				}
			},
			new Object() {
				@Override
				public boolean equals(Object o) {
					Log.d(TAG, "call rhs equals.");
					return true;
				}
			});
		
	// 真偽の判定
	assertTrue(true);
	assertTrue(1 < 2);
	assertFalse(false);
	assertFalse(1 > 2);
	
	// インスタンスの有り無し
	assertNull(null); // 中身がnull
	assertNotNull(new Object()); // インスタンス有り
		
	// 参照先のチェック
	Object expectObject = new Object();
	Object actualObject = expectObject;
	assertSame(expectObject, actualObject);	// 同じインスタンス
	actualObject = new Object();
	assertNotSame(expectObject, actualObject); // 違うインスタンス
}

おまけ

expect側のequalsが使われるとすると、こんなコードにすると
どちらをexpectに置くかで成功と失敗が変わるっていう。
意味があるかは別として、こういうとこでバグると見つけるの大変そうだなぁ

private class SuperClass {
	public Integer a = 0;
	public Integer b = 0;
}

SuperClass classA = new SuperClass() {
	@Override
	public boolean equals(Object o) {
		if(o instanceof SuperClass) {
			return a == ((SuperClass)o).a;
		}
		return false;
	}
};
	
SuperClass classB = new SuperClass() {
	@Override
	public boolean equals(Object o) {
		if(o instanceof SuperClass) {
			return b == ((SuperClass)o).b;
		}
		return false;				
	}
};
	
public void testAssertEquals() {
	
	// aは同じ値
	classA.a = 100;
	classB.a = 100;

	// bは違う値
	classA.b = 200;
	classB.b = 300;

	assertEquals(classA, classB);
	assertEquals(classB, classA); // こっちは失敗するよ
}