テスト戦略 レッスン3

結合テストとE2E

複数コンポーネントを組み合わせて検証する結合テストと、ユーザー視点で確認するE2Eテストの役割を学ぶ

単体テストだけでは見えないもの

個々の関数が正しくても、それらを組み合わせたときに問題が起きることがあります。 たとえば「関数Aが返すデータ形式を関数Bが正しく期待していない」といった境界のズレは、単体テストだけでは検出できません。

// ① repository.ts: DBアクセス層
async function findUserById(db, id) {
  const row = await db.query("SELECT * FROM users WHERE id = ?", [id]);
  return row; // 実は配列を返している(想定は単一オブジェクト)
}

// ② service.ts: ビジネスロジック層
async function getUserName(db, id) {
  const user = await findUserById(db, id);
  return user.name; // user が配列だと undefined になり気づきにくい
}

このような「単体では正しいが組み合わせると壊れる」パターンを検出するのが結合テストの役割です。

結合テストの書き方

結合テストでは、実際のデータベースや外部依存に近いもの(テスト用DB、インメモリDB等)を使い、 複数のモジュールをまたいだ振る舞いを検証します。

import { describe, it, expect, beforeEach } from "vitest";
import { setupTestDatabase } from "./test-utils";
import { getUserName } from "./service";

describe("getUserName (結合テスト)", () => {
  let db;

  beforeEach(async () => {
    db = await setupTestDatabase(); // テスト用DBを毎回初期化
    await db.seed("users", [{ id: 1, name: "田中太郎" }]);
  });

  it("実際のDBから正しくユーザー名を取得できる", async () => {
    const name = await getUserName(db, 1);
    expect(name).toBe("田中太郎");
  });
});

E2Eテストの役割

E2E(End-to-End)テストは、実際のブラウザを使い、ユーザーが行う操作を最初から最後まで再現します。 「ログインしてカートに商品を追加し、決済を完了する」といった主要な業務フローの検証に向いています。

import { test, expect } from "@playwright/test";

test("ユーザーが商品を購入できる", async ({ page }) => {
  await page.goto("/login");
  await page.fill("input[name=email]", "user@example.com");
  await page.fill("input[name=password]", "password123");
  await page.click("button[type=submit]");

  await page.click("text=商品Aをカートに追加");
  await page.click("text=購入手続きへ");

  await expect(page.locator("text=注文が完了しました")).toBeVisible();
});

ポイント

E2Eはすべての画面・パターンを網羅する必要はありません。売上に直結する主要なフローに絞って書くのが実務的です。

結合テスト・E2Eテストの注意点

  • • テスト用DBは各テストの前後で確実にリセットし、テスト間の依存を作らない
  • • E2Eの待機処理は固定のsleepではなく、要素の出現を待つ形にしてフレーキーさを減らす
  • • 外部の決済APIなど本番に影響するものはテスト用のサンドボックス環境を使う

ポイント

  • • 結合テストは単体テストでは見えない「境界のズレ」を検出する
  • • E2Eテストはユーザー視点でシステム全体の一気通貫の動作を確認する
  • • E2Eは主要な業務フローに絞り、網羅性より安定性を優先する
  • • テスト間の依存を作らないよう、状態を都度リセットする

確認クイズ

1 / 3

結合テストが検出しやすい問題として適切なものはどれか?