(続)テストを書かないと品質はやっぱり下がる
前回のエントリにはたくさんのブックマークをいただきました。やっぱり品質と、それを実現するユニットテストやTDDに関する関心は高いですね。そこでもう少しだけ補足することにします。
ユニットテストとレビューは補完的
まず、 r-westさんより頂いた質問に対する回答です。
・xUnit有無で、単体バグは3倍の差が付いた。
→ xUnitは単体バグを相当削減できる。
・しかしxUnitを単に実施しただけでは、単体バグは受け入れテストまで相当数残ってしまった。
→ xUnitも実施するだけでは単体バグの漏れは相当でる。
と言うことでしょうか。
質問に対する回答としては、「はい。xUnitを単に実施しているだけでは漏れるケースがたくさんあります。」となるでしょうか。
では、Actionレイヤを原因とする、「漏れてしまった単体バグ」15件の内の一部をお見せしましょう。(内容は公開用に多少書き直してます)
No | 現象および原因 | 原因レイヤ |
---|---|---|
1 | 特定の条件でボタンを押すとシステムエラーが発生する。データが存在しない場合には、ボタンを操作できないよう、画面の制御する必要があった。 | Action |
2 | エラー一覧表示画面の行番号が0からはじまる。1からはじまるべき。 | Action |
3 | CSVファイル取り込み時にシステムエラーが発生する。金額の比較時にNullチェックが漏れており、NullPointerExceptionが発生する。 | Action |
4 | 納品日(画面項目)を未入力のまま印刷ボタンを押した場合、システムエラーが発生する。Nullチェックが漏れている。 | Action |
5 | 明細に、「訂正」「取消」両方のステータスのものが存在する場合、一覧画面にステータスが正しく表示されない。 | Action |
6 | マスタメンテナンス画面で更新した場合、マスタメンテ画面では正しく更新されているように見えるが、他の画面から見ると更新されていない。内部値用の項目は更新されているが、表示用の項目に値が正しく更新されていない。 | Action |
xUnitテストを書かなかったActionレイヤでのバグは、ほとんどが条件の考慮漏れであり、Serviceレイヤと同様に仕様を掴んだ上でパターンのカバレッジを意識してテストを書いていれば防げたバグが多いです。確かに、単にユニットテストを書いててもダメで、大事なのは正しい仕様を把握することと、粘り強くカバレッジを追い求めることです。
気になったのですが、xUnitの対象コードと対象外コードそれぞれ、
コードの自己レビュー、ピアレビューはどの位されましたでしょうか。
TDDで結果的にテストを通りさえすれば完成というのから、ペアプロした上にさらに翌日頭を冷やしてじっくり自己レビュー・ピアレビューというのまで、相当の差があると思います。
xUnit対象コード・対象外コード、いずれもコードのピアレビューに関しては実施できませんでした。また、自己レビューに関しては明示的に指示をしていませんでしたので、実施したメンバーも、実施しなかったメンバーもいます。(今回私が優先して実施したのは、ユースケース・画面設計書など仕様ドキュメントのレビューです。なぜなら、分散開発(要求は東京、設計実装は福井)を行った関係上、仕様確定の遅れや手戻りを一番のリスクだと認識していたからです。)
コードのピアレビューに関しては、ユニットテストをきっちりと書くのと補完的な関係にあるのでは?という感覚を持っています。つまり、ユニットテストを書かなくても、ピアレビューをきっちり行えば、品質は担保できそうで、特にロジックに密接なDao周りのレビューは効果的でしょう。*1(ただ、資産としてのテストコードは魅力ですし、極力テストコードは書くべきです)
xUnit != TDD
今回の開発が純粋なTDDであるかと言えば、そうではありません。メンバーによってはテストケースを先に検討し、TDD風に進めることもありましたが、チーム全体では「ユニットテストをしっかりと行った」レベルでしょう。確かにxUnitを使うだけでも品質面でかなりのメリットは分かりました。しかし、TDDというプロセスの良さは、コードを書きながら(正しい仕様とカバレッジ、そしてテストのし易さとリファクタリングへの意識を考えさせられることによって)結果的にレビューを受けるのとほぼ同じ効果も得られるところにあると感じています。
*1:今回対象外となったコードには画面周り(JavaScript)もありますが、実はそれなりの数の単体レベルバグが残りました。しかし、画面周りはレビューよりは、ひたすらテストを叩くのが効率的だと感じています。