Skip to content
Published on

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

シェア
Authors

はじめに

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

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

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


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

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

  • 回帰防御: 昨日まで動いていたものが今日壊れたかを教えます。この目的ではテストが実装ではなく外部から観測できる振る舞いに付いていなければなりません。リファクタリングのたびに一緒に直す必要があるテストは、回帰防御の資産ではなく負債です。
  • 設計圧力: テストしにくいコードはたいてい結合が強いコードです。先にテストを書くとインターフェースが利用者の視点で整います。この目的では細かい単位テストが有利で、テストが実装にある程度張り付くことも受け入れます。
  • 仕様と文書: コードが何を保証するかを実行可能な形で残します。読まれることが目的なので、名前と配置が重要です。
  • リリースの信頼: 人が確認しなくても出せるようにします。ここでは統合・契約・E2Eの比重が大きくなります。

ここで最初の衝突が見えます。回帰防御を重んじればテストを実装から引き剥がそうとし、設計圧力を重んじればテストを実装の近くに寄せます。同じコードベースで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日50回回るパイプラインでテスト1本が2秒遅くなれば、年間で数時間が消えます。より大きな損失は、待ち時間が伸びて開発者が文脈を失うことです。
  • 保守コスト: コードが変わるたびに払います。実装の詳細に張り付いたテストはリファクタリングのたびに請求書を送ります。この項目が総コストの大半を占めることはよくあります。
  • 誤検知コスト: 失敗が本物かを確認する時間、そして信頼を失うコストです。最後の項目がもっとも高価です。赤いパイプラインを習慣的に再実行し始めたら、そのテストスイートはすでに資産ではありません。

リターンの項目は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. カバレッジの数字を扱う方法

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

  • 目標値を置こうという側: 数字がなければテストのない領域が静かに育ちます。下限は最低限の規律を作ります。
  • 目標値が有害だという側: カバレッジは実行された行を数えるだけで、検証された振る舞いを数えません。目標を指標にした瞬間、表明のないテスト、ゲッターのテスト、生成コードの計上といった抜け道が現れます。

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

  • 絶対値の目標ではなく差分のゲート: 全体80%のような目標ではなく、今回の変更で新たに追加された行のカバレッジを見ます。既存の負債に触れずに新しいコードの品質だけを管理でき、抜け道の動機もはるかに弱くなります。
  • 低い数字は調査の合図としてのみ使う: カバレッジが低いモジュールは減点対象ではなく調査対象です。テストしにくい構造だという合図であることが多いものです。
  • 高い数字を信頼の根拠にしない: 90%は「10%が危険」ではなく「90%が実行された」という意味にすぎません。実行と検証は別物です。
  • 分岐カバレッジも併せて見る: 行カバレッジだけでは、条件文の片側しか検証していない状態が隠れます。

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


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

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

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

  • どの層が捕まえるべきだったか: 単位 / 統合 / 契約 / E2E / どの層でもない(設計・要求の問題)。
  • なぜ捕まえられなかったか: テストがなかった / あったがモックが実物と違った / 環境差 / データ差 / 並行性とタイミング。

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. 遅く壊れやすいテストを管理する運用規則

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

  • フレーキーテストに所有者と期限を付ける: 再実行で流した瞬間、スイート全体の信頼が削られます。失敗率を自動収集して閾値を超えたら課題を自動生成し、担当者と期限なしには隔離しない規則が必要です。
  • 隔離は削除の予約である: 隔離したテストに期限日を付けます。期限までに直らなければ消します。永久に無効なテストはカバレッジの数字を膨らませるだけで何も守りません。
  • 段階ごとの時間予算を決める: コミット段階5分、マージ前15分のような上限を置き、超えたらテストを追加する前に何を外すかを先に決めます。予算がなければパイプラインは単調に増えます。
  • もっとも遅い20件を定期的に見る: 実行時間の上位リストはたいてい数本が全体を支配します。上位だけ手を入れても総時間が大きく減ることが多いものです。
  • 失敗メッセージを資産として扱う: expected true but got false だけを残すテストは、失敗しても診断の役に立ちません。失敗時にどんな入力とどんな状態だったかを残させると、デバッグ時間が減ります。
  • テストもレビュー対象である: テストコードはレビューでもっとも飛ばされやすい部分ですが、保守コストの大半はそこで発生します。
  • 共有状態をテスト間に残さない: 順序に依存するテストは並列実行を有効にした瞬間ランダムに壊れます。実行順序をランダムに混ぜるオプションを入れておくと、その依存を早期に露呈できます。
  • 時刻と乱数を注入する: 現在時刻や乱数をコードが直接読むと、そのテストはいつか必ず壊れます。月末、うるう年、時間帯の切り替わりで爆発する失敗の多くはここから始まります。

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つに数字で答えれば、比率は結論ではなく計算結果として出てきます。

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


参考資料

  • The Practical Test Pyramid — Martin Fowler — ピラミッドの核心の一文、モデルの限界に対する自己指摘、単位の定義が人によって違うという指摘、E2Eの誤検知と保守コストの評価を引用しました。2026-08-15確認。
  • The Testing Trophy and Testing Classifications — Kent C. Dodds — 4層構成と統合層中心の主張、使われ方に似るほど信頼が高まるという一文、単位定義の統一が無意味だという指摘、Justin Searlsの引用、個別コードベースという前提を引用しました。2026-08-15確認。
  • DORA — Four keys metrics — 変更リードタイムと変更失敗率の定義、速度と安定性が相反しないという研究結果を引用しました。2026-08-15確認。
  • Google SRE Workbook — Canarying Releases — カナリアの定義、5%集団で20%のエラー率が全体1%になるという計算、時間による交絡のため前後比較ではなく同時対照群を使えという推奨を引用しました。2026-08-15確認。
  • 4つの分岐軸、コスト関数の4項目、欠陥記録の2フィールド、1枚の戦略テンプレートは上記資料に出てくるものではなく、本記事で整理した手順です。

関連記事

完全ガイドシリーズ