一月ほど前に「テスト不要論」なるものが炎上しており、思うところがあったので、少しまとめてみました。
ご存じのとおり、テストにはブラックボックステスト・ホワイトボックステストがあります。
しかし、この二つの目的が大きく違うということを知らない人が多いのではないでしょうか。
ブラックボックステスト
ブラックボックステストはコード実装者以外が行うべきものです。
コード実装者は書いてしまった以上ブラックボックスにはできませんし、
テストファストであっても頭の中にこれから書く実装が出来上がっていれば同様です。
ブラックボックステストは設計書通り(設計者の意図通り)にかけているのかという観点でテストし、品質指標とします。
別に設計書通りに書けば品質は高いなんて保障はないので、これを時間の無駄と考える人がある程度いるのではないかと思います。
しかし、プログラマの義務はブラックボックステストではなくホワイトボックステストなのです。
ホワイトボックステスト
ホワイトボックステストテストはコード実装者が行うべきものです。
ホワイトボックステストは、私の書いたコードはこういう動きを保障しているというのをテストコードを用いて伝えているのと同じです。
そのため、リファクタリング、仕様変更、機能追加でコードをいじった結果、始めに保障していた動きができなくなるとテストに通らなくなります。
つまり、ホワイトボックステストはデグレ防止に真価を発揮するのです。
コードがすべて出来上がり、納品前にテストを作成するなんていうのはナンセンスです。
単体テストを行う上で便利なAPI
できるだけ単体テストを行いやすいようにLogicに切り出す方が単体テストは楽ですが、
どうしても切り出しが行えず、複雑な処理をテストで追う必要がある場合があります。
そんな時MockObjectを作成できるAPIは非常に便利です。
私はMockitoを使っています。
public int xxx(YYY yyy) {
if(yyy.isStarted()){
return 1;
} else{
return 0;
}
}
この時YYY#isStarted()はfieldを返すgetterではなく複雑な処理で起動しているのか調べるものなのでYYY#setStarted()はないものとします。
(コーディング規約違反になる機関も多そうですが・・・)
private final static XXX TARGET = new XXX();
@Test
public void xxxTest_YYYが起動している場合1を返す() {
YYY yyy = mock(YYY.class);
when(yyy.isStarted()).thenReturn(true);
assertThat(TARGET.xxx(yyy),is(1);
}
このようにMockを使うことでテストは楽にかけます。
この一見意味のないようなテストも書いておくことにより、リファクタリングの際のミスを減らすことができます。
カバレッジは品質指標として不十分
少し話は変わりますが、マネジメント系の人って「カバレッジ100%」って言葉が好きですよね。
でもカバレッジを100%にするということはすべての分岐を行ったことが確認できただけで、
その分岐内で行われている処理自体が正しいかどうかまでは確認できません。
ちゃんと正しいassertが行われていることも確認してください。
逆にカバレッジ100%にするために絶対発生しないExceptionをスタブを用いて無理やり発生させるなんてテストを書くのは時間の無駄なのでやめましょう。
まとめ
・ブラックボックステストは設計者の義務。
・ホワイトボックステストはプログラマの義務。
・カバレッジだけでは品質を保証できない。