2014年7月30日水曜日

テストピラミッド

テスト戦略やテストアプローチについて調べていたら、テストピラミッドというコンセプトに行き当たった。自分の考えを整理するのにも、他人に考えを伝えるのにも使えそうなのでメモしておく。

考えたのはMike Cohnという人。見覚えがあると思ったら、『アジャイルな見積りと計画づくり』の著者だった。初出は書籍"Suceeding with Agile"。まだ読めていないけれど、Martin FowlerのTestPyramidをとっかかりに調べて分かった範囲で書く。

要は、「Unit test > Subcutaneous Test (サービス層のテスト) > End-to-end test」とピラミッド状になるようにしろよという話。

メソッドを直接叩ける高速で柔軟なUnit testじゃないと、ビジネスロジックの複雑な組み合わせをテストしきれない。GUI操作を経由する低速で融通が利かない (≒目的のテストを書き辛い) End-to-endテストでは、効率が悪すぎる。Unit testの必要性については、アジャイル開発において、技術と品質の重要性は不可欠だ(後編)。Agile Japan 2013 - Publickeyに詳しい。

将来、End-to-endテストも高速になるだろうし、融通が利かないという見方には「レコーディングツールを使えば簡単にテストを書ける」という反論が考えられるけれど、Recordedテストは壊れやすく、壊れてしまったら再レコーディングするハメになる。「レコーディングツールで最初は簡単にテストを書けるという特徴」は、Ice Cream Cornというアンチパターンを招きがちという意味で、危険でさえある。なお、テストの維持コストやRecorded Testの問題については、"xUnit Test Patterns"が詳しい。その上、仮に、End-to-endテストが高速になって、保守性の高いテストを書けたとしても、Non-determinism problemsがあると言っている。

各テストレベルのテスト目的は異なるはずなので、各テストレベルのバランスの取れたテスト戦略・テストアプローチ(Test portfolio) を取るのが健全だと言っている。(少なくとも最初は)簡単だからという理由でEnd-to-endテストの代わりに、Martin FowlerはSubcutaneous test (ユーザーインターフェースのすぐ下から操作するテスト)を推奨している。RESTインタフェースを備えたWebアプリケーションの場合、ブラウザを操作してフォームに入力してパラメータを組み立てる代わりに、REST APIを叩くイメージだろうか。テストコード中でこれを使えば、End-to-endテストのテスト目的 (Test Object) をほぼ満たしつつ、UIに起因する問題を回避できるとしている。

高レベルテストは第二防衛ラインなので、もし失敗したらプロダクトコードを直すだけでなく、ユニットテストを追加すべきだと言っている。