「The Art of Unit Testing with Examples in .NET」を読んでみた
今のプロジェクトで膨大な数のUT/SIの作成、維持管理に苦労しているので、テストケース作成の体系的な知識が必要だと思い「The Art of Unit Testing with Examples in .NET」を読んでみました。
「The Art of Unit Testing with Examples in .NET」
テストしやすい設計
はじめからテスト性を考えた設計を行うための基本的な指針やテクニックが、具体例を交えながら図入りで解説されています。
外部リソースは抽象化する、インスタンスの生成、アクセスはカプセル化し、差替可能とするなど、当たり前のようですが、
今のプロジェクトで、実際にstaticイニシャライザや、コンストラクタ内の膨大なロジックのテストに
苦労しているので、テスト性を考えた設計の大切さを身をもって体感しています。
JMockitのような強力なモックフレームワークを使えば、ある程度はカバーできるのかもしれませんが、
テストのセットアップが複雑するし、予期せぬ不具合が起きた時の対処が難しそうなので、
はじめからテストしやすい設計にしておくにこしたことはないですね。
モックとスタブの区別
モックとスタブのの違いについては、何も知らなくて「なんとなく」使ってたので、目からウロコでした。本当に些細な違いなようですが、変数名やクラス名、メソッド名が大事なのと同じく、
適切に使い分けたほうが無用な混乱を避けられると思います。
テストケースの編成、運用
テストケースを維持管理のパターンが3つ挙げられています。- Abstract test infrastructure class
- Template test class
- Abstract test driver class
早い話が共通的な処理をまとめているだけなので、みんな似たようなことは実践していそうですね。
「Template test class」については、テストケースの実行、テスト対象の生成を抽象メソッドとして定義し、
処理の共通化や、テストケースの実装漏れを無くすことを狙っているようで、
同じインターフェースを実装した複数のクラスのテストケースを作成するときに効果を発揮しそうです。
もっとも、パターンは常に複雑さとのトレードオフなので、過剰に共通化しすぎると、
わかりづらいだけなので、さじ加減が難しそうです。
良いテストケースとは?
良いテストケースの条件として、「信頼できる」「維持メンテできる」「読める」ということが挙げられています。特に維持メンテしやすくするために、「1テストでのアサーションは1つにすべき」という主張は、
1テストケースにたくさん「assertEquals」を書くのが自分中での常識だったので衝撃的でした。
たしかに、複数のアサーションの途中で止まったために、エラーが発生した原因の解析に
苦労したことが多いので、理屈の上では説得力があって納得できますが、テストメソッド数や、
複雑なオブジェクトのアサーション方法の問題から難しそうです。
JUnitなら、テストケースごとにMatcherを実装し、assertThatメソッドで評価すれば
この原則は守れそうですが、手間がかかりますね。
まとめ
テストを書くときに「なんとなく」で実践していることや、よくある問題に対応するための考え方、テクニックが体系的に解説されているので、あまり肩に力を入れずに、さらっと読んでみると良い感じです。
実際にこの本のテクニックのいくつかを使って、テストケースを書きなおしましたが、ベタ書きしていたときと比べて、
「人間が読む気になれる」テストケースに変わったので、テストケース作成で悩んでいるのなら、読むことをお勧めします。