粒度の異なる各自動テストをどの程度書くか悩まれている方は多いと思います。今回は、自動テストの理想的なバランスを示す
テストピラミッドとは何か
テストピラミッドとは、コスト
図1は、テストの粒度をユニットテスト、インテグレーションテスト、E2E
なぜ比率を意識するのか
望ましくない比率の例としては、図2のアイスクリームコーン型や、上下に比べ中央がくびれた砂時計型が挙げられます。どちらも上段のテストが多いのが特徴です。なぜそうなるのでしょうか。
E2Eテストのように、テスト内容がユーザー視点に近く、検証するコード範囲も最も広くなるテストを書けるようになると、これらのテストだけですべての範囲を網羅できると錯覚しがちになります。しかし、これらのテストは決定性が低いため、コードに変更がないのに結果が毎回変わる、コードが正しいのに失敗するなどの不安定な動作が増えます。そういった信頼不能テスト
では上段のテストはすべて不要かと言うとそうではなく、下段のテストだけでもうまくはいきません。たとえばユニットテストだけが書かれている、言わばピラミッドの土台だけといった状況においては、開発したプログラムどうしや外部サービスとの連携などが自動テストの範囲に入っていません。ユニットテストがすべて成功しても、デプロイした本番環境ではシステムが望む動作をしない状況に陥りがちです。結果として、開発者は自動テストの結果だけではシステムの動作に確信を持てなくなります。
つまり、自動テストの粒度において大は小を兼ねませんし、小も大を兼ねません。すべてのテストを書いていく必要があるからこそ、望ましいバランスを考える必要があるのです。
望ましい自動テストの性質
Puppet社が開始し、現在はGoogle社が続けている継続的デリバリの研究には、組織に競争上の優位性をもたらすと認められた自動テストの性質が挙げられています。そのうち、特に次の2つがテストピラミッドの有効性を裏付けています。
- ⓐ テストの大半を統合環境
(本番環境と同等のテスト環境) を必要とせずに実施できること - ⓑ 信頼性の高い自動テストを備えること
ⓐは、ピラミッドの最上段が統合環境の必要なテスト、最上段以外が統合環境不要のテストと整理すると、ピラミッド状に最上段を小さくする重要性につながります。ⓑは、下段を厚くする重要性につながります。信頼性が高いとは、自動テストの成功や失敗が信じられるということです。自動テストが成功すればデプロイ可能、失敗すればコードのどこに問題があるかすぐにわかると確信できる状態です。信頼が失われると、自動テストの記述やメンテナンスに労力が払われなくなります。偽陽性
ピラミッド型の作り方
統合環境なしでその大半を実行し、信頼性が高い自動テスト群を導くピラミッド構造を作るコツは、ユニットテストやE2Eテストのようなテスト範囲ではなく、テストサイズ[2]で段を分割することです。
テストピラミッドは議論が白熱しがちで、
ピラミッド型を作るためには、まずテストの信頼性を最も左右する要素、信頼不能テストに注目します。信頼不能テストに深く関係するのが、GUI
ピラミッドの中段にはMediumテストを配置します。Mediumテストは1つのマシンに閉じたテストですが、コンテナ技術などを使えばデータベースやGUIを伴うテストも実行できます。そのため若干の非決定性があり、テストの速度もそれほど速くなく、テストの並列実行にも制約が発生します。
ピラミッドの最下段にはSmallテストを配置します。Smallテストはそれぞれのテスト実行が単一プロセス内で完結しており、非決定性が入り込む余地はほとんどなく、高速に並列動作し、テスト失敗時の原因も箇所も明白です。
テストピラミッドが最も大事にしているのは、自動テストの信頼性を中長期的に保つことです。テストの数が少ないうちはE2EテストやLargeテスト中心でも信頼性を保てるかもしれませんが、テストの数が増すごとに非決定性やテスト実行速度の遅さが信頼性を蝕み、自動テストが破綻していきます。可能な限り早いうちに、テストを下方の段に移植してピラミッド型に近付ける必要があります。
上段のテストを中段に移植するにはテストダブル[3]を使います。中段のテストを下段に移植するのにもテストダブルが使えますが、オンメモリでテスト対象ロジックを完結させてテストダブルの必要性を減らすような設計変更、たとえばドメイン層の抽出なども非常に効果的です。
ピラミッドの各段の構成比は、数値目標を追い求めて本来の目的を見失わないように注意してください。そのうえで、指標としては
おわりに
自動テストの信頼性を中長期的に保つというテストピラミッドの本質を理解しましょう。