10日で覚えるPlaywrightDay 1: Playwrightの世界へようこそ
books.chapter 110日で覚えるPlaywright

Day 1: Playwrightの世界へようこそ

今日学ぶこと

  • E2Eテストとは何か、なぜ必要なのか
  • テストピラミッドの概念(Unit, Integration, E2E)
  • Playwrightとは何か、その特徴と利点
  • Playwright vs 他のツール(Cypress, Selenium)の比較
  • Playwrightのアーキテクチャ(ブラウザプロトコルによる自動操作)
  • インストールと初期セットアップ
  • 最初のテストを書いて実行する
  • テスト結果の見方

E2Eテストとは何か

Webアプリケーションを開発していると、「ログインフォームに入力して送信したら正しくログインできるか」「商品をカートに追加してチェックアウトまで完了できるか」といった、ユーザーの一連の操作が正しく動くかを確認する必要があります。

これを毎回手動で確認するのは、時間がかかるだけでなく、確認漏れも発生しやすくなります。

E2E(End-to-End)テストとは、実際のユーザーがブラウザでアプリケーションを操作するのと同じ流れを、プログラムで自動化して検証するテスト手法です。

flowchart LR
    subgraph Manual["手動テスト"]
        M1["ブラウザを開く"]
        M2["フォームに入力"]
        M3["ボタンをクリック"]
        M4["結果を目視確認"]
    end
    subgraph E2E["E2Eテスト(自動)"]
        E1["page.goto()"]
        E2["page.fill()"]
        E3["page.click()"]
        E4["expect()で自動検証"]
    end
    M1 --> M2 --> M3 --> M4
    E1 --> E2 --> E3 --> E4
    style Manual fill:#f59e0b,color:#fff
    style E2E fill:#22c55e,color:#fff

なぜE2Eテストが必要なのか

課題 E2Eテストによる解決
手動テストは時間がかかる 自動で数分〜数十分で完了
人間はミスをする 毎回同じ手順を正確に実行
リグレッション(退行)の検出が困難 コード変更のたびに全体を自動チェック
複数ブラウザでの確認が大変 Chromium, Firefox, WebKitで自動実行
CI/CDパイプラインでの品質担保 デプロイ前に自動で品質を検証

テストピラミッド

ソフトウェアテストには、範囲と目的の異なる複数の種類があります。これを体系的に表現したのがテストピラミッドです。

flowchart TB
    subgraph Pyramid["テストピラミッド"]
        E2E["E2Eテスト\n(少数・高コスト・高信頼)"]
        INT["インテグレーションテスト\n(中程度)"]
        UNIT["ユニットテスト\n(多数・低コスト・高速)"]
    end
    E2E --> INT --> UNIT
    style E2E fill:#ef4444,color:#fff
    style INT fill:#f59e0b,color:#fff
    style UNIT fill:#22c55e,color:#fff
テストの種類 対象 速度 コスト
ユニットテスト 関数・コンポーネント単体 速い 低い 入力バリデーション関数のテスト
インテグレーションテスト 複数コンポーネントの連携 中程度 中程度 APIとデータベースの連携テスト
E2Eテスト アプリケーション全体 遅い 高い ユーザー登録からログインまでの一連のフロー

E2Eテストはピラミッドの頂点に位置し、数は少なくても、ユーザーにとって最も重要なシナリオをカバーします。Playwrightは、このE2Eテストを効率的に作成・実行するためのツールです。


Playwrightとは何か

Playwrightは、Microsoftが開発したオープンソースのE2Eテスト・ブラウザ自動化フレームワークです。2020年にリリースされて以降、急速に普及し、現在ではE2Eテストツールの主流の一つとなっています。

Playwrightの主な特徴

flowchart TB
    subgraph Features["Playwrightの特徴"]
        A["マルチブラウザ対応\nChromium / Firefox / WebKit"]
        B["自動待機\nAuto-waiting"]
        C["テスト分離\nBrowser Context"]
        D["並列実行\nParallel Execution"]
        E["強力なデバッグツール\nTrace Viewer / Inspector"]
        F["多言語サポート\nTS / JS / Python / Java / C#"]
    end
    style Features fill:#3b82f6,color:#fff
    style A fill:#8b5cf6,color:#fff
    style B fill:#8b5cf6,color:#fff
    style C fill:#8b5cf6,color:#fff
    style D fill:#8b5cf6,color:#fff
    style E fill:#8b5cf6,color:#fff
    style F fill:#8b5cf6,color:#fff
  1. マルチブラウザ対応: Chromium(Chrome, Edge)、Firefox、WebKit(Safari)の3つのブラウザエンジンをサポート
  2. 自動待機(Auto-waiting): 要素がクリック可能になるまで自動的に待機。明示的なwaitやsleepが不要
  3. テスト分離: 各テストが独立したBrowser Contextで実行されるため、テスト間の干渉がない
  4. 並列実行: テストをワーカープロセスで並列に実行し、テスト時間を大幅に短縮
  5. 強力なデバッグツール: Trace Viewer、UI Mode、Playwright Inspectorなど
  6. 多言語対応: TypeScript/JavaScript、Python、Java、C# をサポート

Playwright vs 他のツール

Selenium / Cypress / Playwright の比較

項目 Selenium Cypress Playwright
開発元 ThoughtWorks(2004年〜) Cypress.io(2017年〜) Microsoft(2020年〜)
対応ブラウザ 全主要ブラウザ Chromium, Firefox, WebKit Chromium, Firefox, WebKit
言語 Java, Python, C#, JS等 JavaScript/TypeScript JS/TS, Python, Java, C#
アーキテクチャ WebDriver経由 ブラウザ内実行 CDPやブラウザプロトコル経由
自動待機 なし(手動で実装) あり あり(より高精度)
並列実行 外部ツール必要 制限あり 標準で対応
複数タブ/ウィンドウ 可能 不可 可能
iframe操作 可能(やや煩雑) 可能(制限あり) 容易
ネットワーク制御 制限あり 強力 強力
実行速度 遅い 速い 非常に速い
学習コスト 中程度 低い 低い

Playwrightを選ぶ理由

  • Seleniumより: 自動待機があり、セットアップが簡単で、実行速度が速い
  • Cypressより: 複数タブ・iframe操作が可能で、マルチブラウザ対応が充実し、並列実行が標準

Playwrightのアーキテクチャ

Playwrightがどのようにブラウザを操作しているか、内部的な仕組みを理解しておきましょう。

flowchart LR
    subgraph TestProcess["テストプロセス"]
        T["テストコード\n(TypeScript)"]
        PW["Playwright\nライブラリ"]
    end
    subgraph BrowserProcess["ブラウザプロセス"]
        B["ブラウザエンジン\n(Chromium/Firefox/WebKit)"]
        P["ページ"]
    end
    T --> PW
    PW -->|"CDP / ブラウザプロトコル"| B
    B --> P
    style TestProcess fill:#3b82f6,color:#fff
    style BrowserProcess fill:#8b5cf6,color:#fff

通信プロトコル

Playwrightは各ブラウザエンジン固有のプロトコルを使ってブラウザと通信します。

ブラウザ プロトコル 説明
Chromium Chrome DevTools Protocol (CDP) Chrome DevToolsと同じプロトコル
Firefox Playwrightプロトコル(独自パッチ) Firefox向けに最適化されたプロトコル
WebKit Playwrightプロトコル(独自パッチ) WebKit向けに最適化されたプロトコル

ブラウザ内で実行されるCypressとの違い

Cypressはテストコードがブラウザ内のiframeで直接実行されます。一方、Playwrightはテストプロセスとブラウザプロセスが分離しています。この設計により、以下が可能になります。

  • 複数ブラウザの同時制御: 別プロセスとして起動するため、複数ブラウザを同時に操作可能
  • 複数タブ・ウィンドウの操作: ブラウザの外からコントロールするため制約がない
  • ネットワークレベルの制御: ブラウザの外側からHTTPリクエスト/レスポンスをインターセプト

インストールと初期セットアップ

前提条件

  • Node.js: バージョン18以上
  • npm: Node.jsに同梱
  • OS: Windows, macOS, Linux

プロジェクトの作成

新しいプロジェクトを作成してPlaywrightをセットアップしましょう。

# 新しいディレクトリを作成
mkdir my-playwright-project
cd my-playwright-project

# Playwrightプロジェクトを初期化
npm init playwright@latest

初期化ウィザードでは以下の質問が表示されます。

? Do you want to use TypeScript or JavaScript? · TypeScript
? Where to put your end-to-end tests? · tests
? Add a GitHub Actions workflow? · false
? Install Playwright browsers? · true

生成されるファイル構成

my-playwright-project/
├── tests/
│   └── example.spec.ts     # サンプルテストファイル
├── tests-examples/
│   └── demo-todo-app.spec.ts # Todoアプリのデモテスト
├── playwright.config.ts      # Playwright設定ファイル
├── package.json
├── package-lock.json
└── tsconfig.json

playwright.config.ts の基本設定

import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  // テストファイルのディレクトリ
  testDir: './tests',

  // 各テストのタイムアウト(30秒)
  timeout: 30000,

  // テストの並列実行
  fullyParallel: true,

  // CI環境ではリトライを有効化
  retries: process.env.CI ? 2 : 0,

  // 並列ワーカー数
  workers: process.env.CI ? 1 : undefined,

  // テストレポーターの設定
  reporter: 'html',

  // 全テスト共通の設定
  use: {
    // ベースURL
    baseURL: 'http://localhost:3000',

    // 失敗時のトレースを記録
    trace: 'on-first-retry',

    // スクリーンショットの設定
    screenshot: 'only-on-failure',
  },

  // テスト対象のブラウザ設定
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

主要な設定項目

設定項目 デフォルト値 説明
testDir './tests' テストファイルのディレクトリ
timeout 30000 各テストのタイムアウト(ms)
fullyParallel true テストの完全並列実行
retries 0 テスト失敗時のリトライ回数
workers CPUコア数の50% 並列ワーカー数
reporter 'list' テストレポーターの種類
use.baseURL なし page.goto('/') のベースURL
use.trace 'off' トレース記録のタイミング

最初のテストを書いてみよう

テストの基本構造

Playwrightのテストは、test 関数と expect アサーションで構成されます。

// tests/my-first-test.spec.ts
import { test, expect } from '@playwright/test';

test('Playwrightの公式サイトにアクセスできる', async ({ page }) => {
  // 1. ページに移動
  await page.goto('https://playwright.dev/');

  // 2. タイトルが "Playwright" を含むことを検証
  await expect(page).toHaveTitle(/Playwright/);

  // 3. "Get started" リンクが表示されていることを検証
  const getStarted = page.getByRole('link', { name: 'Get started' });
  await expect(getStarted).toBeVisible();
});

テストの実行

# 全テストを実行
npx playwright test

# 特定のテストファイルを実行
npx playwright test tests/my-first-test.spec.ts

# 特定のブラウザで実行
npx playwright test --project=chromium

# UIモードで実行(インタラクティブ)
npx playwright test --ui

# ヘッド付きモードで実行(ブラウザが表示される)
npx playwright test --headed

複数のテストを書く

// tests/example.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Playwright公式サイト', () => {
  test('トップページにアクセスできる', async ({ page }) => {
    await page.goto('https://playwright.dev/');
    await expect(page).toHaveTitle(/Playwright/);
  });

  test('Get startedページに遷移できる', async ({ page }) => {
    await page.goto('https://playwright.dev/');

    // "Get started" リンクをクリック
    await page.getByRole('link', { name: 'Get started' }).click();

    // Installationの見出しが表示されることを検証
    await expect(
      page.getByRole('heading', { name: 'Installation' })
    ).toBeVisible();
  });

  test('検索機能が動作する', async ({ page }) => {
    await page.goto('https://playwright.dev/');

    // 検索ボタンをクリック
    await page.getByRole('button', { name: 'Search' }).click();

    // 検索ダイアログが表示されることを検証
    await expect(page.getByRole('dialog')).toBeVisible();
  });
});

テスト結果の見方

コマンドライン出力

テストを実行すると、以下のような出力が表示されます。

Running 3 tests using 3 workers

  ✓  1 [chromium] › example.spec.ts:4:3 › Playwright公式サイト › トップページにアクセスできる (1.2s)
  ✓  2 [chromium] › example.spec.ts:9:3 › Playwright公式サイト › Get startedページに遷移できる (1.8s)
  ✓  3 [chromium] › example.spec.ts:20:3 › Playwright公式サイト › 検索機能が動作する (1.5s)

  3 passed (4.2s)

テスト結果のステータス

ステータス 記号 意味
Passed テスト成功
Failed テスト失敗
Skipped - テストがスキップされた
Timed out タイムアウトで失敗
Flaky リトライで成功(不安定なテスト)

HTMLレポート

テスト失敗時やレポート設定時に、HTMLレポートが生成されます。

# HTMLレポートを表示
npx playwright show-report

HTMLレポートでは以下の情報を確認できます。

  • 全テストの結果一覧
  • 各テストの実行時間
  • 失敗したテストのエラーメッセージ
  • スクリーンショット(設定時)
  • トレース情報(設定時)

Trace Viewer

テストが失敗した原因を詳しく調べるには、Trace Viewerが非常に便利です。

// playwright.config.ts でトレースを有効化
use: {
  trace: 'on-first-retry',  // 最初のリトライ時にトレース記録
}

Trace Viewerでは以下を確認できます。

  • テストの各ステップのスクリーンショット
  • 各操作時のDOMスナップショット
  • ネットワークリクエストの内容
  • コンソールログ
# トレースファイルを開く
npx playwright show-trace trace.zip

まとめ

概念 説明
E2Eテスト ユーザー操作を自動化してアプリケーション全体を検証するテスト
テストピラミッド Unit → Integration → E2E の3層構造。E2Eは少数で重要シナリオに集中
Playwright Microsoftが開発したマルチブラウザ対応のE2Eテストフレームワーク
自動待機 要素がアクション可能になるまでPlaywrightが自動で待つ機能
Browser Context テストごとに独立したブラウザコンテキストで分離実行される仕組み
CDP Chrome DevTools Protocol。PlaywrightがChromiumと通信する際のプロトコル
Trace Viewer テスト実行の各ステップを詳細に確認できるデバッグツール

重要ポイント

  1. E2Eテストは手動テストを自動化し、リグレッションを防ぐために不可欠
  2. Playwrightはブラウザプロセスの外側から制御するため、複数タブやiframeの操作が自由にできる
  3. 自動待機機能により、テストコードにsleepやwaitを明示的に書く必要がない
  4. npm init playwright@latest で簡単にプロジェクトをセットアップできる

練習問題

問題1: 基本

テストピラミッドの3つの層をそれぞれ説明し、各層で書くべきテストの具体例を挙げてください。また、E2Eテストをピラミッドの頂点に配置する理由を述べてください。

問題2: 応用

PlaywrightとCypressのアーキテクチャの違いを図で説明し、Playwrightのアーキテクチャがもたらす利点を3つ挙げてください。特に、複数タブの操作が可能になる理由を述べてください。

チャレンジ問題

npm init playwright@latest で新しいプロジェクトをセットアップし、以下の要件を満たすテストを作成してください。

  1. playwright.config.ts を編集して、Chromiumのみで実行されるようにする
  2. 好きなWebサイトにアクセスするテストを書く
  3. ページタイトルの検証、特定の要素の表示確認を含める
  4. npx playwright test で実行し、HTMLレポートを確認する

参考リンク


次回予告: Day 2では「テストの基本構造」について学びます。test.describetest.beforeEachtest.afterEach などの構造化要素と、Playwrightのフィクスチャの仕組みを理解しましょう。