LASSIC Media らしくメディア
テストピラミッドとは?テストの数を層ごとに配分する考え方
監修・編集責任者:牛尾 昭昌(株式会社LASSIC 執行役員)
この記事の結論
- テストピラミッドは、単体テストを最も多く、画面から通すE2Eテストを最も少なくする、自動テストの配分の考え方です。
- E2Eテストに頼るアイスクリームコーンや結合テストが抜けた砂時計になると、CIが遅くなり、失敗の原因も絞りにくくなります。
- トロフィーやハニカムとの違いは単体テストの定義の差によるところが大きく、比率より先に層の定義と数え方を決めます。
※ 本記事は2026年10月時点の公式情報(省庁・公的機関、および製品やサービスを提供する事業者が公開している資料)に基づきます。
テストピラミッドは、自動テストを粒度の違う層に分け、下の層ほど数を多く、上の層ほど少なくするという配分の考え方です。下には関数やクラスを1つずつ確かめる単体テスト、真ん中には部品どうしや部品とデータベースのつなぎ目を確かめる結合テスト、上には画面から全体を通して動かすE2E(エンドツーエンド)テストが入ります。上の層ほど遅く、壊れやすく、直す手間も大きいため、数を絞るのが基本です。
本記事では、Martin Fowler氏の解説やGoogle Testing Blogの記事などをもとに、層ごとの数・速さ・費用の関係、ピラミッドの崩れ方、トロフィー型やハニカム型との違い、CIでの配分を整理します。
目次
テストピラミッドとは
Martin Fowler氏は、テストピラミッドを、さまざまな自動テストを使って釣り合いのとれたテストの組み合わせを作るための考え方だと説明しています。要点は、画面を通して動かす高いレベルのテストより、低いレベルの単体テストをずっと多く持つことです。*1 この図が広く知られたのは、Mike Cohn氏が2009年の著書『Succeeding with Agile』で取り上げてからです。
Ham Vocke氏の解説によると、Cohn氏の元の図は下から単体テスト、サービステスト、ユーザーインターフェーステストの3層です。*2 層の名前は資料によって異なり、Vocke氏も名前にこだわりすぎないよう勧めています。覚えておくべきなのは、粒度の違うテストを書くこと、高いレベルになるほど数を少なくすることの2つです。なお、単体テストは部品1つを依存先から切り離して確かめるテスト、結合テストは部品どうしや部品と外部のつなぎ目を確かめるテストを指します。
| 層 | 確かめる範囲 | 数 | 1件の重さ |
|---|---|---|---|
| E2Eテスト(上) | 画面から外部サービスまで全体を通す | 最も少なく | 遅い・壊れやすい・原因が絞りにくい |
| 結合テスト(中) | 部品どうし、部品とDBやAPIのつなぎ目 | 中くらい | 単体より遅く、E2Eより軽い |
| 単体テスト(下) | 関数・クラスなど部品1つ | 最も多く | 速い・安定・失敗箇所がすぐ分かる |
層ごとの数・速さ・費用の関係
上の層を少なくする理由は、速さと費用にあります。Fowler氏は、画面を通して全体を動かすテストを「壊れやすく、書くのに費用がかかり、実行に時間がかかる」ものだとまとめています。*1 機能を少し直しただけで多くのテストが壊れ、ビルドの時間も延びます。
Google Testing Blogの記事は、よいフィードバックの条件として、速いこと、信頼できること、失敗の場所を切り分けられることの3つを挙げています。単体テストはこの3つを満たしやすく、単体テストでは0.1秒でも遅いとみなされるほどです。*3 E2Eテストは製品全体のビルドと配置を待ってから動き、不具合の場所も絞れません。真ん中の層について、Fowler氏は、画面ではなくAPIなどのサービス層を通すテストを挙げています。E2Eテストの利点の多くを得ながら、画面の部品を扱う複雑さを避けられる形です。
比率の数値を示した一次資料は多くありません。Google Testing Blogの記事は、最初の見当として、単体テスト70%、結合テスト20%、E2Eテスト10%の割合をGoogleはよく勧めるとしつつ、正確な配分はチームごとに違い、大切なのはピラミッドの形を保つことだとしています。*3 Fowler氏とVocke氏の記事は、比率の数値を示していません。
ピラミッドには例外もあります。Fowler氏は、上の層のテストが速く、安定し、直しやすいなら、下の層のテストは要らないという例外も認めています。
崩れ方:アイスクリームコーンと砂時計
ピラミッドが崩れた形として、よく挙がるのがアイスクリームコーンです。Google Testing Blogの記事は、E2Eテストに主に頼り、結合テストは少なく、単体テストはさらに少ない形を、逆ピラミッドまたはアイスクリームコーンと呼んでいます。*3 Fowler氏は、画面の操作を録画して再生する道具に頼った自動化が、この形に陥りやすいと述べています。
もう一つの崩れ方が砂時計です。単体テストはたくさんあるのに、結合テストで確かめるべきところをE2Eテストで確かめてしまい、真ん中が細くなった形です。部品どうしのつなぎ目の不具合を、画面から全体を通して探すことになります。
アイスクリームコーンの害について、同じ記事は複数の実体験をもとにした架空の例を示しています。毎晩すべてのE2Eテストを流し、その90%以上が通ることを機能完成の条件にしたチームは、開発の区切りが1週間遅れました。*3 原因探しに時間がかかる、連携先や試験環境の障害で結果が何日も台無しになる、大きな不具合の陰に小さな不具合が隠れる、修正が効いたかを翌日まで知れない、といった問題が重なったためです。
トロフィー型・ハニカム型との違い
ピラミッドへの反論として知られるのが、テスティングトロフィーとテスティングハニカムです。テスティングトロフィーは、Kent C. Dodds氏が2018年2月6日の投稿で示した、JavaScriptのアプリケーションでテストの種類ごとの投資対効果を考える目安です。*4 層は下から静的解析、単体テスト、結合テスト、E2Eテストで、結合テストをいちばん厚くします。Dodds氏は、1つのコードベースの中で考えるもので、マイクロサービスには当てはめて考えていないとも書いています。
テスティングハニカムは、Spotifyの技術ブログが2018年に示したマイクロサービス向けの形です。*5 マイクロサービスで最も複雑なのはサービスの中ではなくほかとのやり取りであり、単体テストが多すぎるとテストまで直さないとコードを変えられなくなる、というのが理由です。結合テストに重点を置き、実装の詳細を確かめるテストは少しだけ、他のシステムの正しさで合否が決まるテストはできれば持たないとしています。
ただ、違いは見かけほど大きくないという見方もあります。Fowler氏は2021年の記事で、論争の多くは単体テストの定義の違いから来ていると指摘しました。*6 依存先を代役に置き換える孤立型(solitary)と、本物の依存先とつないだまま確かめる社交型(sociable)の単体テストを区別し、ハニカムの支持者が言う結合テストは、社交型の単体テストにかなり近いとしています。
| 形 | 最も厚くする層 | 想定している対象 |
|---|---|---|
| ピラミッド | 単体テスト | 特定の対象に限らない一般的な目安 |
| トロフィー | 結合テスト(土台に静的解析) | JavaScriptのアプリケーション、1つのコードベース |
| ハニカム | 結合テスト | マイクロサービス |
具体例:CIで層を分けて数える
CIでの配分は、層の種類ではなく速さと範囲で決めます。Vocke氏は、速いテストをパイプラインの前の段に、時間のかかるテストを後ろの段に置くよう勧めています。次の例は、GitHub Actionsで層ごとにジョブを分けた設定です。
# .github/workflows/test.yml
on: pull_request
jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install pytest && pytest tests/unit --junit-xml=unit.xml
integration:
needs: unit # 単体テストが通ってから動く
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install pytest && pytest tests/integration --junit-xml=integration.xml
e2e:
needs: integration # 結合テストが通ってから動く
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install pytest && pytest tests/e2e --junit-xml=e2e.xml
needsに書いたジョブは、指定したジョブが成功してから動き、前のジョブが失敗すればスキップされます。*7 単体テストで落ちた変更に、時間のかかるE2Eテストを流さずに済みます。
配分が崩れていないかは、数えてみないと分かりません。pytestは–junit-xmlを付けると、CIサーバーが読めるJUnit XML形式の結果を出力します。*8 次のスクリプトは、この結果をディレクトリ名で層に分け、件数・割合・合計時間を出します。
# pyramid_report.py:JUnit XMLを層ごとに数える
import sys
import xml.etree.ElementTree as ET
from collections import defaultdict
LAYERS = ["unit", "integration", "e2e"] # 下の層から順に
count, secs = defaultdict(int), defaultdict(float)
for path in sys.argv[1:]:
for tc in ET.parse(path).iter("testcase"):
layer = tc.get("classname").split(".")[1] # tests.unit.test_x → unit
count[layer] += 1
secs[layer] += float(tc.get("time", 0))
total = sum(count.values())
for name in LAYERS:
print(f"{name:<12}{count[name]:>3}件 {count[name] / total:6.1%} {secs[name]:6.2f}秒")
for low, high in zip(LAYERS, LAYERS[1:]):
if count[high] > count[low]:
print(f"注意: {high} が {low} より多い(逆ピラミッドの兆し)")
税込み金額の計算を単体テスト6件、データベースから税率を読む結合テスト2件、HTTPで結果を取るE2Eテスト1件で確かめる小さなサンプルに当てると、単体6件(66.7%)、結合2件(22.2%)、E2E1件(11.1%)と出ました。上の層が下の層より多ければ注意の行が出ます。時間も並べると、件数ではピラミッドでも時間ではE2Eテストが大半、という状態に気づけます。
層ごとに時間の上限を決める方法もあります。ビルドツールのBazelは、テストの大きさをsmall・medium・large・enormousで宣言させ、既定の時間の上限をそれぞれ60秒、300秒、900秒、3600秒としています。*9
使いどころ
テストピラミッドが役に立つのは、上の層で不具合が見つかったときです。Fowler氏は、高いレベルのテストで見つかった不具合は、直す前に単体テストで再現するよう勧めています。Vocke氏も、上の層だけが失敗したら下の層のテストを書くこと、テストをできるだけ下の層へ押し下げることを経験則に挙げ、同じことを複数の層で確かめる重複も避けるべきだとしています。
どの形を目安にするかは、システムの作りで選びます。業務ロジックが厚いバックエンドはピラミッド、画面の部品の組み合わせが中心のフロントエンドはトロフィー、サービス間のやり取りが中心のマイクロサービスはハニカムが、それぞれの提唱者の想定に近い使い方です。サービス間の約束を確かめる方法は「コントラクトテスト(Pact)導入を外注で進める」で扱っています。
E2Eテストと画面のテストを同じものと考えないことも大切です。Fowler氏は両者を別の軸だとし、作り込んだ画面の振る舞いの大半はJavaScriptの単体テストで確かめるべきだとしています。画面の見た目の崩れは「ビジュアルリグレッションテスト導入を外注で進める」の方法で、E2Eテストとは別に確かめられます。
つまずきやすい点
1つ目は、比率を目標の数値にしてしまうことです。70%・20%・10%は最初の見当にすぎません。Fowler氏も2021年の記事で、どの種類のテストを何%書くかの議論は本題から目をそらすものだ、というJustin Searls氏の言葉を引いています。*6 境界がはっきりし、速く安定して動き、意味のある理由でだけ失敗するテストを書くほうが大切だ、という趣旨です。
2つ目は、層の定義がチームの中でずれていることです。データベースにつなぐテストを単体テストと呼ぶ人も、結合テストと呼ぶ人もいます。依存先を本物にするか代役にするかで層を決め、テスト設計の文書に書いておきます。代役の使い分けは「テストダブルとは」をご覧ください。
3つ目は、不安定なE2Eテストを放っておくことです。結果が安定しないテストは信頼を失い、本当の不具合を見つけたときでさえ無視されがちになります。失敗したE2Eテストの切り分け方は「E2Eテスト自動化の保守と失敗対応、外部エンジニアとのテスト体制」で扱っています。
外部に委託するときに確認しておきたい点
テスト自動化を外部に委託するときは、まず層の定義と配分の考え方を文書で合わせます。どの依存先を代役にするか、E2Eテストで確かめる利用の流れはどれか、層ごとの時間の上限はいくらかを決めておかないと、納品されたテストがアイスクリームコーンでも気づけません。基盤づくり全体の進め方は「QAテスト自動化を外注する基盤構築ガイド」で扱っています。
次に、層ごとの件数と時間を定期的に報告してもらいます。結合テストの依存先の用意は「Testcontainersで統合テストを外注で進める」、アプリのE2Eテストは「アプリのE2Eテスト自動化(Appium/Maestro)を外注する進め方」、網羅率の関門は「テストカバレッジ計測とゲート導入を外注する要点」が参考になります。最後に、壊れやすい上の層のテストを誰が直し、不安定なテストをどう隔離するかを、運用の取り決めに入れておきます。
まとめ:テストピラミッドで確かめておきたい3つの点
テストピラミッドを実務に生かすうえで、確かめておきたい点は3つです。第一に、依存先を本物にするか代役にするかで層の定義をそろえ、文書に残すこと。第二に、層ごとの件数と時間を数え、アイスクリームコーンや砂時計になっていないかを定期的に見ること。70%・20%・10%は目標ではなく最初の見当です。第三に、上の層で見つかった不具合は下の層のテストで再現してから直し、CIでは速いテストを前の段に置くことです。
よくある質問
テストピラミッドの比率は70対20対10が正解ですか
正解の比率はありません。Google Testing Blogの記事は70%・20%・10%を最初の見当として示し、正確な配分はチームごとに違うとしています。
テストピラミッドは古い考え方ですか
トロフィーやハニカムのように結合テストを厚くする考え方もありますが、Martin Fowler氏は、違いの多くは単体テストの定義の差から来ていると指摘しています。
E2Eテストは書かないほうがよいのですか
そうではありません。システム全体が通ることを確かめられるのはE2Eテストだけです。主要な利用の流れに絞って少なめに持ち、細かな場合分けは下の層に任せます。
テストの設計と自動化のご相談
元請(プライムベンダー)として、テストの層の配分の設計からCIへの組み込み、保守・運用までご提案します。
Remoguとリラシクなら、テストの自動化やCIの整備に加わるITエンジニアも探せます。
Remoguは、リモート前提で全国から即戦力のITプロ人材を調達するサービスです。リラシクは、扱う求人がすべてリモートワークのITエンジニア専門転職エージェントです。どちらもLASSICが運営しています。
出典
- *1 参考:Martin Fowler「TestPyramid」(martinfowler.com、2012年5月1日、2017年11月15日改訂)(https://martinfowler.com/bliki/TestPyramid.html)。出典:テストピラミッドの定義、画面経由のテストの性質、サービス層を通すテスト、前提と例外(注2)、Etymology(名称の由来)を参照。解説記事のため補助として参照(2026年10月確認)
- *2 参考:Ham Vocke「The Practical Test Pyramid」(martinfowler.com、2018年2月26日)(https://martinfowler.com/articles/practical-test-pyramid.html)。出典:The Test Pyramid、Avoid Test Duplication、デプロイメントパイプラインでのテストの置き方を参照。解説記事のため補助として参照(2026年10月確認)
- *3 参考:Mike Wacker「Just Say No to More End-to-End Tests」(Google Testing Blog、2015年4月22日)(https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html)。出典:End-to-End Tests in Practice、Building the Right Feedback Loop、Testing Pyramid(70/20/10の目安、逆ピラミッド・砂時計)を参照(2026年10月確認)
- *4 参考:Kent C. Dodds「The Testing Trophy and Testing Classifications」(2021年6月3日)(https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications)。出典:テスティングトロフィーの提示(2018年2月6日の投稿)と想定する対象(1つのコードベース)を参照(2026年10月確認)
- *5 参考:André Schaffer、Rickard Dybeck「Testing of Microservices」(Spotify Engineering、2018年1月11日)(https://engineering.atspotify.com/2018/01/testing-of-microservices)。出典:Traditional test strategy、Microservices test strategy(テスティングハニカム)を参照(2026年10月確認)
- *6 参考:Martin Fowler「On the Diverse And Fantastical Shapes of Testing」(martinfowler.com、2021年6月2日)(https://martinfowler.com/articles/2021-test-shapes.html)。出典:ピラミッドとハニカム・トロフィーの違い、孤立型(solitary)と社交型(sociable)の単体テスト、Justin Searls氏の言葉の引用を参照。解説記事のため補助として参照(2026年10月確認)
- *7 参考:GitHub Docs「Workflow syntax for GitHub Actions」(https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax)。出典:ジョブの needs キーワード(jobs.job_id.needs)の説明を参照(2026年10月確認)
- *8 参考:pytest「Managing pytest’s output」(https://docs.pytest.org/en/stable/how-to/output.html)。出典:Creating JUnitXML format files を参照(2026年10月確認)
- *9 参考:Bazel「Test encyclopedia」(https://bazel.build/reference/test-encyclopedia)。出典:テストのsizeとtimeoutの対応、timeoutごとの時間の上限を参照(2026年10月確認)