Playwright テスト ガイド: Next.js アプリケーションの E2E テスト

Playwright を使用して、Next.js アプリケーションの信頼できるエンドツーエンドのテストを作成します。セットアップ、ページ オブジェクト、認証テスト、ビジュアル リグレッション、CI/CD 統合をカバーする完全なガイド。

E

ECOSIRE Research and Development Team

ECOSIREチーム

2026年3月5日4 分で読める693 語数

Playwright テスト ガイド: Next.js アプリケーションの E2E テスト

エンドツーエンド テストは、認証フローの破損、フォーム送信の失敗、ナビゲーション エラー、クロスブラウザー レンダリングの問題など、単体テストで見逃されるバグをキャッチします。 Microsoft によって構築された Playwright は、マルチブラウザーのサポート、自動待機機能、および強力なデバッグ ツールを備えた主要な E2E テスト フレームワークになりました。

重要なポイント

  • Playwright テストは、単一のテスト スイートから Chromium、Firefox、WebKit にわたって実行されます
  • 自動待機により、要素が操作可能になるのを待ってから対話するため、不安定なテストが排除されます。
  • 認証状態をテスト全体で共有して、実行を高速化できます。
  • GitHub Actions との CI 統合により、すべてのプル リクエストの自動テストが可能になります

プロジェクトのセットアップ

インストール

npm init playwright@latest

これにより、Playwright がインストールされ、構成ファイルが作成され、ブラウザーのバイナリがダウンロードされます。 For Next.js projects, configure the web server to start automatically:

// playwright.config.ts
import { defineConfig } from "@playwright/test";

export default defineConfig({
  testDir: "./e2e",
  timeout: 30000,
  retries: process.env.CI ? 2 : 0,
  use: {
    baseURL: "http://localhost:3000",
    screenshot: "only-on-failure",
    trace: "on-first-retry",
  },
  webServer: {
    command: "npm run dev",
    port: 3000,
    reuseExistingServer: !process.env.CI,
  },
  projects: [
    { name: "chromium", use: { browserName: "chromium" } },
    { name: "firefox", use: { browserName: "firefox" } },
    { name: "webkit", use: { browserName: "webkit" } },
  ],
});

最初のテストを作成する

基本的なナビゲーション テスト

// e2e/navigation.spec.ts
import { test, expect } from "@playwright/test";

test("home page loads and displays title", async ({ page }) => {
  await page.goto("/");
  await expect(page).toHaveTitle(/ECOSIRE/);
  await expect(page.getByRole("heading", { level: 1 })).toBeVisible();
});

test("navigation to services page", async ({ page }) => {
  await page.goto("/");
  await page.getByRole("link", { name: "Services" }).click();
  await expect(page).toHaveURL(/services/);
  await expect(page.getByRole("heading", { name: /Services/ })).toBeVisible();
});

フォーム送信テスト

test("contact form submission", async ({ page }) => {
  await page.goto("/contact");

  await page.getByLabel("Name").fill("Test User");
  await page.getByLabel("Email").fill("[email protected]");
  await page.getByLabel("Message").fill("This is a test message");
  await page.getByRole("button", { name: "Send" }).click();

  await expect(page.getByText("Message sent")).toBeVisible();
});

ページオブジェクトパターン

保守性を高めるために、ページ インタラクションをページ オブジェクトにカプセル化します。

// e2e/pages/login.page.ts
import { Page, expect } from "@playwright/test";

export class LoginPage {
  constructor(private page: Page) {}

  async goto() {
    await this.page.goto("/login");
  }

  async login(email: string, password: string) {
    await this.page.getByLabel("Email").fill(email);
    await this.page.getByLabel("Password").fill(password);
    await this.page.getByRole("button", { name: "Sign In" }).click();
  }

  async expectLoggedIn() {
    await expect(this.page).toHaveURL(/dashboard/);
  }

  async expectError(message: string) {
    await expect(this.page.getByText(message)).toBeVisible();
  }
}

テストでの使用:

test("successful login", async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login("[email protected]", "password123");
  await loginPage.expectLoggedIn();
});

認証テスト

共有認証状態

認証状態を保存することで、毎回のテストの前にログインを回避します。

// e2e/auth.setup.ts
import { test as setup } from "@playwright/test";

setup("authenticate", async ({ page }) => {
  await page.goto("/login");
  await page.getByLabel("Email").fill("[email protected]");
  await page.getByLabel("Password").fill("admin-password");
  await page.getByRole("button", { name: "Sign In" }).click();
  await page.waitForURL("/dashboard");

  // Save authentication state
  await page.context().storageState({ path: ".auth/user.json" });
});

playwright.config.ts で設定します。

projects: [
  { name: "setup", testMatch: /auth\.setup\.ts/ },
  {
    name: "authenticated",
    dependencies: ["setup"],
    use: { storageState: ".auth/user.json" },
  },
],

視覚的な回帰テスト

スクリーンショットを比較して、意図しない視覚的な変更を検出します。

test("home page visual regression", async ({ page }) => {
  await page.goto("/");
  await expect(page).toHaveScreenshot("home-page.png", {
    maxDiffPixelRatio: 0.01,
  });
});

初回実行時に、Playwright はベースラインのスクリーンショットを保存します。後続の実行はベースラインと比較され、差がしきい値を超える場合は失敗します。変更が意図的である場合は、--update-snapshots を使用してベースラインを更新します。


API モック

決定論的テストのために API 応答を模擬します。

test("displays products from API", async ({ page }) => {
  await page.route("/api/products", async (route) => {
    await route.fulfill({
      status: 200,
      contentType: "application/json",
      body: JSON.stringify([
        { id: 1, name: "Product A", price: 29.99 },
        { id: 2, name: "Product B", price: 49.99 },
      ]),
    });
  });

  await page.goto("/products");
  await expect(page.getByText("Product A")).toBeVisible();
  await expect(page.getByText("Product B")).toBeVisible();
});

CI/CD の統合

GitHub アクション

name: E2E Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/

失敗したテスト レポートは、スクリーンショット、トレース、ビデオ録画など、デバッグ用のアーティファクトとしてアップロードされます。


デバッグツール

  • Playwright Inspector: ステップバイステップで実行するために --debug フラグを使用してテストを実行します
  • トレース ビューア: トレースを開いて、すべてのアクション、ネットワーク リクエスト、DOM スナップショットを確認します。
  • Codegen: npx playwright codegen を実行してブラウザーの操作を記録し、テスト コードを生成します。
  • VS Code 拡張機能: 要素をクリックして配置することで、VS Code から直接テストを実行およびデバッグします

ベストプラクティス

  1. ロールベースのセレクターを使用: CSS セレクターよりも getByRole、getByLabel、getByText を優先します。
  2. ハードコードされた待機を避ける: page.waitForTimeout() の代わりに自動待機を信頼します。
  3. テストを分離する: 各テストは独立している必要があり、他のテストに依存しないでください。
  4. 実装ではなくユーザー フローをテスト: コードがどのように機能するかではなく、ユーザーが行うことに焦点を当てます。
  5. テストを高速に行う: セットアップに API ショートカットを使用します (UI ではなく API 経由でテスト データを作成します)
  6. CI で実行: すべてのプル リクエストはマージ前に E2E テストに合格する必要があります

よくある質問

Q: Playwright と Cypress を比較するとどうですか?

Playwright は複数のブラウザ (Chromium、Firefox、WebKit) をネイティブにサポートしていますが、Cypress は主に Chromium をターゲットとしています。 Playwright は並列実行が高速で、複数のタブ/ウィンドウを処理します。 Cypress は学習曲線が若干容易で、タイムトラベル デバッグが強力です。

Q: 不安定なテストはどのように処理すればよいですか?

Playwright の自動待機により、ほとんどの不安定さが解消されます。残りの問題については、Web ファースト アサーション (ロケーターを期待) を使用し、タイミング依存の動作のテストを回避し、CI で再試行を構成します。トレース レポートは、断続的な障害の根本原因を特定するのに役立ちます。

Q: すべてのページをテストする必要がありますか?

重要なユーザー フロー (認証、コア ビジネス ワークフロー、フォーム送信、支払いフロー) に焦点を当てます。すべてのページに E2E テストが必要なわけではありません。コンポーネント レベルをカバーするには単体テストと統合テストを使用してください。

Q: E2E テストにはどれくらい時間がかかりますか?

個々のテストは 30 秒以内に完了する必要があります。中規模のアプリケーション (50 ~ 100 のテスト) の完全なスイートは、並列実行で 10 分以内に実行されます。


次は何ですか

Playwright を使用した E2E テストにより、ユーザーの観点からアプリケーションが正しく動作するという確信が得られます。重要なフローから始めて、アプリケーションの成長に応じて対象範囲を拡大してください。

テスト自動化のヘルプについては ECOSIRE にお問い合わせ、品質が保証された ERP 導入については Odoo 実装サービス をご覧ください。


ECOSIRE が発行 -- エンタープライズ ソフトウェア ソリューションによるビジネスの拡大を支援します。

E

執筆者

ECOSIRE Research and Development Team

ECOSIREでエンタープライズグレードのデジタル製品を開発。Odoo統合、eコマース自動化、AI搭載ビジネスソリューションに関するインサイトを共有しています。

WhatsAppでチャット