LabHub

ブログ

テスト戦略 完全ガイド: ピラミッド論争ではなく判断基準

한국어English日本語

はじめに

このブログにはすでにテストを扱った韓国語の完全ガイドが複数あります。ソフトウェアテスト戦略 完全ガイドはどんなテストの種類がありどう使うかを、プロパティベーステスト実践は特定の技法を、検証設計 — テストを信頼の根拠として見るは検証を個人の力量の観点で扱います。3本ともにどんなテストが存在し、どう書くかについての記事です。

本記事は違います。チームが自分の比率を自分で決める方法を扱います。ピラミッドとトロフィーのどちらかを選ばず、その論争が実際にはどの軸の上で起きているのかを分解します。軸が分かれば「うちのスタックではどちらか」に自分で答えられ、それは他人の結論を写すより長持ちします。

先に結論を述べるとこうです。比率は答えではなく結果です。欠陥がどこから出るか、統合環境の構築がどれだけ高くつくか、E2Eがどれだけ空振りするかを測れば、比率は自動的に導かれます。


1. テストが存在する理由: 回帰防御か設計圧力か

テストの議論が空回りするときは、たいてい参加者が異なる目的を前提にしています。テストが存在する理由は大きく4つあり、目的が違えば良いテストの形も変わります。

ここで最初の衝突が見えます。回帰防御を重んじればテストを実装から引き剥がそうとし、設計圧力を重んじればテストを実装の近くに寄せます。同じコードベースで2つの目的がぶつかったら、「このテストはリファクタリングのときに一緒に直してよいか」という質問1つで整理できます。回帰防御用なら駄目で、設計圧力用なら構いません。チームがこの区別に名前を付けておくと、レビューでの議論が半分に減ります。


2. ピラミッドとトロフィー — 論争の実際の軸

2-1. 2つの主張の原文

テストピラミッドはMartin Fowlerの整理が広く引用されます。核心は一文です。"Write lots of small and fast unit tests. Write some more coarse-grained tests and very few high-level tests that test your application from end to end." 上に行くほど遅く高くつくので数を減らせ、ということです。

注目すべきは、同じ記事が自分のモデルの限界を自ら認めていることです。"the concept of the test pyramid falls a little short if you take a closer look" と書き、中間層について "service test is a term that is hard to grasp" と述べ、最近のフロントエンド環境では "UI tests don't have to be on the highest level" と付け加えます。最上段のE2Eについては "notoriously flaky and often fail for unexpected and unforeseeable reasons" であり "require a lot of maintenance and run pretty slowly" と評価します。

テスティングトロフィーはKent C. Doddsの整理です。静的検査、単位、統合、E2Eの4層に分け、統合層をもっとも大きく取ります。根拠は投資あたりの信頼度であり、彼の表現では "The more your tests resemble the way your software is used, the more confidence they can give you" です。

2-2. 論争を終わらせようとすること自体が問題だという指摘

重要なのは、トロフィー側もこの論争を正解探しとは見ていない点です。Doddsは同じ記事で単位テストの定義が "24 different definitions of unit test" ほどに割れると紹介し、"Any attempt to come to a single definition for all these terms is a futile endeavor" と書きます。そしてJustin Searlsの言葉を引用します。"People love debating what percentage of which type of tests to write, but it's a distraction."

Fowler側も同様です。"If you ask three different people what 'unit' means in the context of unit tests, you'll probably receive four different, slightly nuanced answers."

つまり両陣営の代表的文献がそろって、比率論争は本質ではないと言っています。それでも現場の論争が終わらない理由は、比率という1つの数字の裏に、異なる複数の条件が隠れているからです。

2-3. 実際の分岐軸4つ

軸1  「単位」の境界をどこに引くか
     関数1つ = 単位     → 単位テスト数が急増、ピラミッドに見える
     モジュール = 単位   → 同じテストが「統合」に分類され、トロフィーに見える

軸2  統合環境の構築コストはいくらか
     コンテナで30秒     → 統合の比重を上げるほうが合理的
     専用ステージング要  → 統合を増やすとフィードバック周期が崩れる

軸3  E2E層の誤検知率はいくらか
     1%未満             → E2Eを信頼の根拠に使える
     10%以上            → 信号ではなく雑音、層自体を減らすべき

軸4  テストの主目的は何か
     回帰防御           → 振る舞い中心、大きい単位、モックは最小限
     設計フィードバック  → 実装の近く、小さい単位、モック許容

4つの軸にチームの実際の値を入れると、比率は議論なしに出てきます。コンテナベースの統合環境が30秒で立ち上がり、E2Eの誤検知率が8%で、チームの主目的が回帰防御なら、結果はトロフィーに近い形になります。逆にドメインロジックが厚く統合環境が高価ならピラミッドに近づきます。どちらも間違っておらず、2つの記事が異なる軸の値を持つコードベースを前提にしていただけです

2-4. 移すときに必ず確認すること

Dodds本人も、トロフィーが個別のコードベースを対象としたモデルであり、マイクロサービスやサーバーレス構成にそのまま適用できるとは限らないと述べています。どのモデルでも原文が前提にした文脈を一緒に運ばなければなりません。絵だけを写せば、他人の軸の値でうちの比率を決めることになります。


3. 「単位」という言葉は合意されたことがない

3-1. 定義のスペクトラム

比率論争の半分は用語の問題です。同じテストがチームによって単位にも統合にも分類されます。

狭い ←──────────────────────────────────────────────→ 広い

関数1つ         クラス1つ      モジュール1つ    プロセス1つ
協力者を全部モック 一部をモック    内部は実物       外部だけ代役
                               DBはインメモリ    DBはコンテナ

FowlerもDoddsも指摘するとおり、このスペクトラムのどこにも標準の境界はありません。だから「単位テストの比率70%」という目標は境界を決める前には何の意味もありません。境界を動かすだけで、同じコードベースの数字が20%から80%まで動きます。

3-2. 名前ではなく性質で呼ぶ

実務でよく通る回り道は、分類名を捨てて性質で呼ぶことです。

この4つの値が決まれば名前は不要です。CIパイプラインの段階構成も名前ではなくこの値で分けます。「3秒以内に終わり外部依存のないテスト」はコミットごとに、「コンテナが要るテスト」はマージ前に、「ステージングが要るテスト」はデプロイパイプラインで回します。


4. コスト関数として見る: 作成・実行・保守・誤検知

テストを資産ではなくコストとリターンが同居する契約として見ると、判断が楽になります。コストは4項目です。

リターンの項目は1つです。防いだ欠陥の期待値、つまりそのテストがなければ本番まで届いた欠陥の確率とコストの積です。

数字を入れると感覚がつかめます。E2Eテスト1本の作成に4時間、実行に40秒、四半期に2回の手直しに2時間かかるとします。1日30回回るパイプラインなら実行だけで年間およそ68時間が消え、保守まで足せば1年の総コストは80時間を超えます。同じロジックを検証する単位テスト5〜6本の総コストは、その半分にも満たないことが多いものです。作成コストだけを比べればE2Eが安く見えますが、総コストではたいてい逆です。

ここから実務的に有用な規則が出ます。同じ欠陥を2つの層で捕まえているなら、高いほうを消します。E2Eが検証するロジック分岐を単位テストがすでに全部覆っているなら、そのE2Eはコストだけが残ります。E2Eには層間の接続(ルーティング、認証、シリアライズ、設定)のように、下の層が原理的に見られないものだけを残します。

逆方向の誤りもよくあります。下の層に押し込めない検証を無理に単位テストにすると、モックが実物とずれた瞬間に全部緑なのに本番が壊れます。判断基準は「この欠陥がこの層で原理的に見えるか」であって「この層が安いか」ではありません


5. 何をモックで置き換えるか

モックの使用範囲はこの分野でもっとも古い論争の1つで、いまだに合意がありません。

5-1. 2つの立場

5-2. 分岐軸と実務基準

論争の軸は置き換える対象が制御可能かです。次の基準はおおむねよく働きます。

モックで置き換える            実物を使う
─────────────────────       ─────────────────────
外部システム(決済、メール)  同じコードベース内の協力者
非決定的要素(時刻、乱数)    純粋計算と値オブジェクト
再現しにくい失敗              コンテナで立ち上がるストレージ
遅いI/O(数秒以上)           インメモリで代替できるストレージ

さらに守るべき規則が2つあります。第一に、自分が所有していないインターフェースを直接モックにしません。外部SDKを包む薄いアダプタを作り、そのアダプタを代役に替えます。外部SDKの挙動を想像でモックに固めると、その想像が外れたときにどのテストも失敗しません。第二に、モックを使ったならそのモックが実物と同じであることを別の層で確認しなければなりません。契約テストや少数の実通信テストがその役割を果たします。

5-3. モックの代わりに使える代役たち

モックの一語でまとめると論争が長引きます。代役にも種類があり、保守コストが違います。

モックを使うかどうかよりも、この検証に必要な最小の代役はどれかのほうが良い問いです。多くの論争は、厳密なモックを既定値として使う習慣から始まります。


6. カバレッジの数字を扱う方法

カバレッジの目標値もまた合意のない領域です。論争の軸をまず整理します。

どちらも正しいのです。だから数字を使いつつ使い方を変えるのが現実的です。

カバレッジが答えられない問いは「このテストが実際に欠陥を捕まえるか」です。これを直接測る方法もあります。コードに小さな変異を自動で仕込み、テストがその変異を捕まえるかを見る方式です。捕まえられなかった変異が多ければ、実行はされるが検証はないコードが多いという意味です。実行コストが大きく全スイートに常時適用するのは難しいものの、中核ドメインのモジュールに一度回すだけでも、表明が空白の区域が明らかになります


7. 欠陥が実際にどこから出るか — データで比率を決める

7-1. 4週間の記録で十分

比率を決めるもっとも確実な方法は議論ではなく記録です。本番の欠陥とロールバックに次の2つのフィールドを付けるだけで、4週間以内に方向が見えます。

2つのフィールドの分布がそのまま投資先です。統合層が捕まえるべきだったが半分なら統合を増やすのが正しく、モックが実物と違ったが半分ならモックを減らすか契約テストを入れるのが正しいのです。どの層でもないが半分なら、テストを増やしても欠陥は減りません。そのときは要求定義と設計レビューのほうへ投資を移すべきです。

7-2. デリバリ指標と併せて見る

DORAは4つの指標を定義します。デプロイ頻度、変更のリードタイム(変更が "committed to version control" から "deployed in production" までにかかる時間)、変更失敗率("The ratio of deployments that require immediate intervention following a deployment")、失敗デプロイからの復旧時間です。

テスト戦略の効果は変更失敗率とリードタイムの組み合わせで確認します。テストを増やしたのに変更失敗率が動かないなら誤った層に投資したのであり、変更失敗率は下がったのにリードタイムが大きく伸びたならコストがリターンを超えたのです。DORAはこの2つが相反しないと述べています。"DORA's research has repeatedly demonstrated that speed and stability are not tradeoffs." どちらかが悪化したなら、やむを得ない折衷ではなく設計の問題として見るほうが妥当です。

7-3. 本番も検証の層である

すべての欠陥をリリース前に捕まえることはできません。Google SREワークブックはカナリアを "a partial and time-limited deployment of a change in a service and its evaluation" と定義し、残りの集団を対照群とします。ここから出る計算が有用です。5%のカナリア集団でエラー率が20%でも、全体のエラー率は1%にとどまります。つまりカナリアは欠陥をユーザーに見せない装置ではなく、露出の規模をエラーバジェットの中に閉じ込める装置です。

同じ文書は、時間による変化が観測値の大きな交絡要因なので、前後比較ではなく同時に走る対照群と比較するよう勧めます。テストの層とリリースの層は代替ではなく補完であり、E2Eを増やすかカナリアを精緻にするかは同じ予算を争う選択です。エラーバジェットの観点はSLI/SLO/エラーバジェットにあります。


8. 遅く壊れやすいテストを管理する運用規則

戦略文書よりも実際の品質を左右するのは、この運用規則です。

FowlerがE2Eを notoriously flaky と表現したのは道具の問題ではなく、その層の構造的性質です。E2E層は増やす層ではなく、狭く保って強く管理する層と見るほうが現実的です。


9. チームのテスト戦略を1枚で書く

戦略は文書ではなく合意です。1枚を超えれば誰も読みません。

1. 私たちがテストで買おうとしているもの
   (回帰防御 / 設計フィードバック / リリース信頼の優先順位)

2. 層の定義と実行場所
   速い層:   3秒以内、外部依存なし          → コミットごと
   統合層:   コンテナ必要、30秒以内         → マージ前
   E2E層:    ステージング必要、10分以内     → デプロイパイプライン

3. モックを使う場所と使わない場所
   代役: 外部の決済・メール、時刻、乱数
   実物: 自前のストレージ(コンテナ)、内部モジュール

4. カバレッジ規則
   差分カバレッジの下限だけをゲートに使い、全体目標値は置かない

5. 時間予算
   コミット5分 / マージ前15分、超過時は追加の前に削除を先に

6. フレーキー対応
   失敗率が閾値を超えたら自動で課題化、隔離には担当者と期限日が必須

7. 見直し周期
   四半期に1回、欠陥分布のデータで2・3項を更新

この文書の値打ちは内容よりも更新履歴にあります。欠陥分布が変われば比率も変わるべきで、その変更根拠が残っていて初めて次の人が理由を理解できます。ソフトウェアテスト戦略 完全ガイドと併せて読むとよいでしょう。


クイズ: 理解度を確認しましょう

クイズ1: 隣のチームがトロフィーを使うと言って統合の比重を70%に移しました。そのまま追随してよいか

正解: 統合環境の構築コスト、E2Eの誤検知率、単位の定義、テストの主目的という4つの値を自チーム基準で確認してから決めます。

説明: トロフィーとピラミッドは、それぞれ異なる軸の値を持つコードベースを前提にしたモデルです。統合環境がコンテナで30秒で立ち上がるチームと、専用ステージングが必要なチームの最適比率が同じになるはずがありません。Dodds本人も、トロフィーが個別のコードベースを対象としたモデルでマイクロサービス構成にそのまま適用できるとは限らないと述べています。比率は写すものではなく軸の値から導くものです。

クイズ2: カバレッジが60%から85%に上がったのに本番の欠陥は変わりません。何を確認するか

正解: 欠陥がどの層で捕まえられるべきだったかの分布をまず確認します。

説明: カバレッジは実行された行を数えるだけで、検証された振る舞いを数えません。表明の弱いテストが増えれば数字は上がり欠陥はそのままです。より多いのは誤った層に投資した場合です。欠陥の半分が統合の接点から出るのに単位テストだけ増やせば、数字だけが上がります。どの層が捕まえるべきだったかとなぜ捕まえられなかったかの2つを4週間記録するだけで方向が見えます。

クイズ3: 決済ゲートウェイ連携でモックを使うか実物を使うかを決めます。判断基準は何か

正解: 外部システムなのでモックで置き換えますが、直接モックを作らず薄いアダプタを作ってそのアダプタを代役にし、モックが実物と同じであることを別の層で確認します。

説明: 外部システムは制御できず、遅く、費用も発生するので、多くのテストで代役が必要です。問題は、自分が所有していないインターフェースを想像でモックに固めると、その想像が外れたときにどのテストも失敗しないことです。アダプタで境界を所有してから代役化し、契約テストや少数の実通信テストでアダプタの仮定を定期的に検証する構成が安全です。

クイズ4: E2Eスイートが1日3回ランダムに失敗します。再実行の自動化を入れるべきか

正解: いいえ。再実行は信号を消す措置であり、失敗率を指標として収集し、所有者と期限の付いた隔離・修正の手順へ回すべきです。

説明: 再実行の自動化は誤検知コストを表面上だけ下げ、実際にはスイート全体の信頼を削ります。赤いパイプラインを習慣的に回し直すようになると、本物の欠陥が混じっても区別できません。E2Eは構造的に誤検知が多い層なので、層を狭く保ち、下の層が原理的に見られないものだけを残すほうがよいのです。隔離には必ず期限日を付け、永久に無効なテストが生まれないようにします。

クイズ5: テストを大量に追加した結果、変更失敗率は半分になったがリードタイムは2倍になりました。どう判断するか

正解: やむを得ない折衷ではなく設計の問題と見て、どのテストが時間を支配しているか、同じ欠陥を2つの層で重複して捕まえていないかをまず確認します。

説明: DORAは速度と安定性が相反しないと繰り返し示してきました。どちらかが大きく悪化したなら、たいていはパイプライン構成の問題です。実行時間の上位リストは少数のテストが支配していることが多く、E2Eが検証する分岐を単位テストがすでに全部覆っていれば、そのE2Eはコストだけが残ります。段階ごとの時間予算を決め、追加の前に削除を先に決める規則が必要です。


おわりに

ピラミッドとトロフィーのどちらが正しいかという問いに答えはありません。両モデルの著者がともにそう述べており、とりわけDoddsが引用した一文は率直です。比率論争そのものが注意をそらす、というものです。

代わりに答えのある問いはこうです。うちのチームで単位の境界はどこか。統合環境を立ち上げるのにいくらかかるか。E2Eの誤検知率は何パーセントか。前四半期の欠陥はどの層が捕まえるべきだったか。 この4つに数字で答えれば、比率は結論ではなく計算結果として出てきます。

そしてその計算は一度で終わりません。スタックが変わり、道具が速くなり、欠陥分布が動けば、比率もついて動かねばなりません。テスト戦略の品質は比率の正確さではなく更新周期にかかっています


参考資料


関連記事

完全ガイドシリーズ

コメント

まだコメントはありません。

ログインするとコメントできます