JUnitでテストコードを書く時に気を付けていること

JUnitと言えばJavaで書いたプログラムの単体テストを自動化するフレームワークです。
今回はこのJUnitでテストコードを作成するにあたって気を付けていることを
紹介してみようと思います。

まず始めにサンプルのテストコードですが、「MyClass」というクラスに定義された「convertValue(int value)」という静的メソッドがあると仮定します。
そのメソッドの正常系と異常系が正常に動作することを検証するテストコードを以下に示します。
public class MyClassTest {
// convertValue 正常ケース(小さい値)
// 10以下の値を指定すると10倍の値を返すこと
@Test
public void testConvertValueOkSmallValue() throws Exception {
assertEquals(0, MyClass.convertValue(0));
assertEquals(50, MyClass.convertValue(5));
assertEquals(100, MyClass.convertValue(10));
}
// convertValue 正常ケース(大きい値)
// 10より大きい値を指定すると20倍の値を返すこと
@Test
public void testConvertValueOkLargeValue() throws Exception {
assertEquals(220, MyClass.convertValue(11));
assertEquals(400, MyClass.convertValue(20));
}
// convertValue 引数異常
// 引数に負の値を指定するとIllegalArgumentExceptionがスローされること
@Test
public void testConvertValueExceptionMinusValue() throws Exception {
try {
MyClass.convertValue(-1);
} catch (IllegalArgumentException e) {
return;
}
fail();
}
}
実際に作成するテストコードはもっと規模が大きく複雑なものになります。
上記サンプルは何気なく書いたテストコードですが、以下のことに気を付けています。
テスト対象メソッド名とテストの概略を書く
コメント欄にテスト対象のメソッド名とテストの概略を1行に書いています。
何のメソッドのどんな検証を行うかを1行に書いておくことで、後でテストコードを見た時にテスト内容が分かりやすくなります。
更に、Grepなどを駆使することでテスト対象メソッドの検証内容のリストを抽出することもできます。
期待動作の内容を書く
コメント欄にどんな動作を期待するかを書いています。
上記のサンプルは簡単なテストコードなので検証内容が分かりやすく問題ないのですが、複雑になると後から見た時に何の検証を行うテストコードなのかが分からなくなってしまいます。
テストメソッドの名前には連番を使用しない
テストメソッドの名前にはなるべく連番を使用しないようにしています。
後でテスト対象メソッドに仕様変更が発生したりした場合、当然テストコードも修正することになるのですが、場合によってはテストメソッドを連番の中間に挿入したくなることがあります。
そうなると後ろの番号を全てずらさないといけなくなるので非常に面倒な作業が発生することになります。
また、メソッド名から検証内容が推測しにくくなったりなど、いくつかのデメリットがあるので連番は使用しないようにしています。
1つのテストメソッドで複数の検証を行わない
1つのテストメソッドの中で複数の検証を行うとメソッド名を決めにくくなったり、テスト実行時にテストが途中で停止した場合に停止した箇所以降の検証ができなくなったりなどのデメリットが発生しますのであまりお勧めできません。
一度の一括実行で全てのNGを検出できるようにするためにも、1メソッド1検証が望ましいと考えます。
これらの内容はテスト対象が小規模であれば無視してもそれほど問題にはなりませんが、ある程度規模が大きくなると一気に影響が出始めます。
テストコードの量産を始める前に後々のことも含めて書き方を予め検討してから作業に取り掛かることで、メンテナンスしやすいテストコードになるかもしれません。
