たなかのJava日記

どんなことをやったか(学んだか)、どこで詰まったか(わからなかったか)、どこで工夫したかの記録です。

効果的にテストケースを書くためには

効果的にテストケースを書くためには

■バグを顕在化させることのできるパターンを網羅しているかが一番の鍵
テストは多くのパターンを列挙すればよいというものではない。
パターンが多いと実行時間が長くなってテスト実行が億劫になるデメリットもある。
パターンが多いとテスト自体のメンテナンス工数も増えてしまう問題もある。
このことから、テストに品質はパターン数ではなく、バグを顕在化させることのできるパターンを網羅しているかで決まると言えます。

■どのような箇所に、どのようにテストケースを書くのか
①条件分岐する箇所・境界値前後
「年齢によって酒の販売が許可される・されない」など、引数やその他条件によって動作が変わる。
このようなメソッドでは極力すべての条件分岐を網羅できるようにテストを書きます。
20歳未満は酒の提供禁止ですが、誤って20歳未満は提供可能な実装をしてしまうこともあるためです。
また20歳、19歳、21歳などの境界前後の値でも期待通りの動作かを検証する必要があります。

②異常値
プログラムを実装するときは正常動作することのみを検証しがちです。
テストケースを洗い出す場合は、異常値を渡すことも検討すべきです。
例えば、Stringの引数を受け取る場所でnullを渡したらどうなるのか、
年齢を受け取る場所で負の値を渡したらどうなるのか、などです。
nullや負の値を渡すことを許容しないのであれば、メソッドのJavadocにその旨を明記することが必要です。
また、許容しない値を渡したら例外IllegalArgumentExceptionが投げられることを確認するテストケースを書いたりすることで仕様が明確になります。

③不安な箇所
実装したあとで動作確認をしたくなるような、不安を覚える箇所にテストケースを書きます。
バグが発生していないことを確認、確信するための重要な箇所です(精神的にも)

④重要度の高い箇所、金勘定が関係する箇所
同じ画面表示という機能でも、社内向けシステムでレイアウトが崩れても業務に差支えはありません。
しかし、お客さま向けがめんで他人の個人情報が表示されてしまえば重大な障害になります。
また、株取引システムで株価の計算ミスがあれば、証券会社だけでなく経済も揺るがすことになります。
業務上、重要度が高くてバグの発生を許容しがたい箇所には優先的にテストを書くようにします。

⑤バグが判明した箇所
テストを十分に記述したつもりでもバグは発覚します。
バグが発覚した際、焦ってJUnitテストケースを書かずに実装コードを直してしまうと、
同様のバグが発生した際に検出できないだけでなく、
そもそも「バグを修正できた」、という確信を持つことができません。
バグを見つけたら直してしまう前に「現象を再現し、失敗する」テストケースを記述し、
その上で実装を修正するようにします。

⑥細かい粒度のテスト
単体テストは、メソッドやクラスを対象とした細かい単位のテストになります。
結合テストは、複数のクラスやメソッドを組み合わせた処理です。
総合テストは、一気通貫で動作を確認するテストです。
(システムにログインしてフォームに必要事項を入力送信を行うなど)
ユーザー目線に立つとシステムが動作している様子が分かりやすい総合テストを優先しがちですが、
テストする対象のコードが多ければ多いほど、シナリオは複雑になり、テストすべきパターンが漏れがちです。
単体テストで細かい粒度てテストがしっかりできていればバグが検出されにくくなります。
テストはより細かい単位でしっかりパターンを網羅しておくのが大切です。

⑦わかりやすいテストケース名
テスト対象のメソッド1つにつきテストメソッドが1つしかないのであれば、テスト対象のメソッドと同じでかまいません。
しかし、色々なパターンでテストをする分けている場合は、メソッド名を工夫するのが良いです。
add1()、add2()などというメソッド名でもコンパイルでき、テストは実行できます。
しかし、テストは一種の仕様書であり、失敗したときはバグ報告書でもあります。
対象のメソッドへどのような挙動を期待しているのか(仕様)、
どのようなシナリオでテストを行っているのか(失敗時のバグ報告)などが
わかるような、わかりやすいメソッド名が好ましいです。
またプロジェクトの公用語が日本語であれば日本語でメソッド名を書くのも有りです。
テストが失敗した際、どういった問題があるのか一目でわかります。