
単体テスト vs 結合テスト vs E2Eテスト:テストピラミッドの考え方
1. はじめに
「テストを書きましょう」と言われても、どのレベルのテストをどれくらい書けばよいのか、明確な基準を持っているチームは意外と多くありません。単体テストばかり書いてもUIのバグは防げませんし、逆にE2Eテストばかりに頼ると実行時間が肥大化し、CI/CDのボトルネックになります。
本記事では、テスト設計の基本指針である「テストピラミッド」の考え方をもとに、単体テスト・結合テスト・E2Eテストそれぞれの役割と、実務でのバランスの取り方を解説します。
2. テストピラミッドとは
テストピラミッドは、テストを3つの階層に分け、下位層ほど多く、上位層ほど少なく書くべきだという考え方を図式化したものです。
/\
/ \ E2Eテスト(少ない)
/----\
/ \ 結合テスト(中程度)
/--------\
/ \ 単体テスト(多い)
/------------\
この形が推奨される理由は、下位層(単体テスト)ほど実行速度が速く、書くコストが低く、失敗時の原因特定が容易だからです。逆に上位層(E2Eテスト)は実行速度が遅く、書くコストが高く、失敗時にどこが原因か切り分けにくいという特性があります。
多くの現場で起きがちな失敗は、このピラミッドが「逆三角形」や「アイスクリームコーン型」になってしまうことです。つまり、UIを通したE2Eテストばかりに頼り、単体テストがほとんど書かれていない状態です。この場合、テストスイート全体の実行に時間がかかり、CI/CDのフィードバックサイクルが遅くなります。
3. 単体テスト(Unit Test)
役割
単体テストは、関数やクラスなど、コードの最小単位を対象に、外部依存(データベース、API、ファイルシステムなど)を排除した状態で検証するテストです。
特徴
・実行速度が速い:外部依存がないため、数千件のテストでも数秒〜数十秒で完了する
・失敗原因の特定が容易:対象範囲が狭いため、失敗した瞬間にどのロジックが壊れたか特定できる
・書く量が最も多い:ピラミッドの土台として、ロジックの分岐やエッジケースを網羅的にカバーする
外部依存がある処理(DB呼び出しなど)は、モックやスタブに置き換えてテストします。モックの使い分けについては別途詳しく扱う価値のあるテーマですが、基本方針は「単体テストでは実際のDBやAPIには接続しない」ことです。
4. 結合テスト(Integration Test)
役割
結合テストは、複数のモジュールやコンポーネントを組み合わせた際の連携が正しく動作するかを検証します。実際のデータベースやAPIクライアントを使う(あるいは実物に近いテスト用インスタンスを使う)ケースが多く、単体テストではカバーできない「モジュール間のつなぎ込み」の不具合を検出します。
特徴
・実際の依存関係を使う:テスト用データベースやコンテナ化されたミドルウェアを使い、実環境に近い状態で検証する
・単体テストより実行速度が遅い:DBアクセスやネットワーク通信が発生するため、単体テストの数倍〜数十倍の時間がかかる
・API層・DB層・外部サービス連携の検証に向く:例えば「APIエンドポイントがリクエストを受けてDBに正しく保存するか」といったシナリオ
Dockerコンテナでテスト用のデータベースを都度起動し、テスト終了後に破棄する構成(Testcontainersなど)を使うと、CI環境でも再現性高く結合テストを実行できます。
5. E2Eテスト(End-to-End Test)
役割
E2Eテストは、実際のユーザー操作を模倣し、システム全体が一気通貫で期待通りに動作するかを検証します。ブラウザを自動操作し、画面遷移やフォーム入力、表示内容までを含めて確認します。
特徴
・ユーザー視点での正しさを検証できる:単体・結合テストが通っていても、UI側の実装ミスや連携漏れによる不具合はE2Eテストでしか検出できない場合がある
・実行速度が最も遅い:ブラウザの起動、画面描画の待機などが発生するため、1シナリオあたり数秒〜数十秒かかることも珍しくない
・壊れやすい(Flaky):画面のちょっとしたレイアウト変更やタイミング問題でテストが不安定になりやすい
・数を絞るべき:全画面・全操作を網羅しようとせず、「購入完了までの主要フロー」など、ビジネス上クリティカルなシナリオに絞って書く
6. 実務でのバランスの取り方
目安となる比率
厳密な数値基準はありませんが、一般的な目安として以下のような比率がよく参照されます。
・単体テスト:全体の70%程度
・結合テスト:全体の20%程度
・E2Eテスト:全体の10%程度
これはあくまで目安であり、プロジェクトの性質(バッチ処理中心か、UI中心かなど)によって最適な比率は変わります。重要なのは「E2Eテストに偏りすぎていないか」を定期的に見直すことです。
CI/CDパイプラインでの実行タイミングの分離
実行速度の違いを踏まえ、パイプライン内で実行タイミングを分けるのが実務的です。
単体・結合テストはPRごとに毎回実行し、実行に時間のかかるE2Eテストはmainブランチへのマージ時やナイトリービルドでのみ実行する、といった分離をすることで、開発者へのフィードバック速度と網羅性を両立できます。
7. どのテストから書き始めるべきか
新規にテストを整備する場合、以下の優先順位で着手すると効果的です。
1.ビジネスロジックの中核となる単体テスト:金額計算、権限判定、在庫引当など、バグが起きた際の影響が大きい処理から着手する
2.主要なAPIエンドポイントの結合テスト:注文作成、決済処理など、DBとの連携込みで正しさを保証したい処理
3.クリティカルなユーザーフローのE2Eテスト:購入完了までのフロー、ログイン、会員登録など、最も重要な数シナリオに絞る
いきなり全レイヤーを完璧にカバーしようとせず、まずは影響範囲の大きい処理から段階的にテストを積み上げていくアプローチが現実的です。
8. まとめ
テストは、単にバグを見つけるためのものではなく、ソフトウェアを安心して変更・改善し続けるための土台となる重要な仕組みです。テストピラミッドの考え方を取り入れ、それぞれのテストが担う役割を理解することで、品質と開発スピードのバランスを取りながら、効率的なテスト戦略を実現できます。
また、単体テスト・結合テスト・E2Eテストのどれか一つが優れているというわけではありません。それぞれの特性を理解し、目的に応じて適切に組み合わせることが重要です。限られた開発時間の中で、重要なロジックやユーザーに影響の大きい機能を優先してテストすることで、品質を維持しながら開発効率を高めることができます。
近年では、CI/CDやDevOpsの普及により、テストは開発プロセスに欠かせない存在となっています。適切なテスト設計は、バグの早期発見だけでなく、安心してリリースできる環境づくりや、将来の機能追加・リファクタリングを支える大きな力になります。











