用語集 · テストの基礎
E2E テスト(エンドツーエンドテスト)
英語: End-to-end test
別名: E2Eテスト, エンドツーエンドテスト, E2E, end-to-end testing
定義
実際に完全デプロイされたシステムで、UI や公開 API からデータベースまでを通しで動かし、ユーザージャーニー全体を検証するテストです。
エンドツーエンド(E2E)テストは、ユーザーと同じ方法でシステムを動かし、すべてのレイヤーを本物のまま使います。ブラウザ、フロントエンド、バックエンドサービス、データベース、キュー、そして可能であれば外部サービスとの連携もです。下位レベルのテストでは答えられない「実際のジャーニーで、全体が本当に連携して動くのか」という問いに答えます。最も現実的な信頼性を最も高いコストで得られるため、E2E テストはテストピラミッドの頂点に位置します。
具体例(Playwright)
import { test, expect } from '@playwright/test';
test('guest can buy a product', async ({ page }) => {
await page.goto('/');
await page.getByRole('searchbox', { name: 'Search' }).fill('desk lamp');
await page.keyboard.press('Enter');
await page.getByRole('link', { name: 'Desk Lamp' }).click();
await page.getByRole('button', { name: 'Add to cart' }).click();
await page.getByRole('link', { name: 'Checkout' }).click();
await page.getByLabel('Email').fill('guest@example.com');
await page.getByRole('button', { name: 'Place order' }).click();
await expect(page.getByRole('heading', { name: 'Thank you for your order' })).toBeVisible();
});
1 つのテストが検索、カタログ、カート、チェックアウト、注文の各サービスを横断します。カートサービスが価格を誤ってシリアライズしていれば、各サービスのユニットテストがすべて合格していても、このテストで検出できます。
数を絞る理由
- 遅い。 ユニットテストが数ミリ秒なのに対し、1 件あたり数秒から数分かかります。
- フレーキーになりやすい。 動く部品が多いほど、タイミングの問題、共有データ、環境の不安定さが増えます。
- 原因を特定しにくい。 「チェックアウトが失敗した」の原因は、十数個のサービスのどれにでもあり得ます。
- 保守コストが高い。 UI の変更が多くのテストに波及します。
そのため、E2E テストは会員登録、購入、中核となる業務フローといった重要なビジネスジャーニーに限定し、バリエーション(すべてのバリデーションルール、すべての割引種別)はユニットや API のレベルでカバーします。
安定させるには
- 条件ベースの待機を使います。Playwright の自動待機や Web ファーストアサーション、Selenium の
WebDriverWaitなどで、固定のスリープは決して使いません。 - テストデータは API で作成します。 セットアップで UI をクリックして作るのではなく、各テストに専用のデータを用意します。
- 安定したロケーターを使います。 レイアウトに依存する XPath ではなく、ロール、ラベル、テスト ID を使います。
- コードを構造化します。 ページオブジェクトなどを使い、UI の変更を 1 か所の修正で済むようにします。
「E2E テスト」と「システムテスト」は重なる部分があります。システムテストはテストレベルを指し、E2E はすべてのレイヤーを通過するテストのスタイルを表します。