AI

E2Eテスト比較:Playwright vs Cypress vs Puppeteer でブラウザ自動化を実装する

オープンソースラボ編集部2026年6月14日

E2Eテスト比較:Playwright vs Cypress vs Puppeteer でブラウザ自動化を実装する

フロントエンドアプリのユーザーシナリオを自動テストするE2E(End-to-End)テストフレームワークは現代のCI/CDに不可欠です。Playwright(Microsoft製・最新・多ブラウザ)・Cypress(DX重視・リアルタイムデバッグ)・Puppeteer(Google Chrome Team製・Chrome特化)の3つが2026年のE2Eテストデファクトスタンダードです。

E2Eテストフレームワークを使う理由

  • 回帰テスト自動化: ユーザーの操作シナリオを自動化してリリースごとの手動テストを排除
  • CI統合: GitHub Actionsでプルリクエストごとにヘッドレスブラウザテストを実行して品質保証
  • クロスブラウザ検証: Chrome・Firefox・Safari・Edge・モバイルブラウザの互換性を自動確認
  • 視覚的回帰: スクリーンショット比較でUIの意図しない変更を検知

主要フレームワークの概要

Playwright

2020年公開(Microsoft)、TypeScript製のOSSです。GitHubスター68k+。Chrome・Firefox・WebKit(Safari)・Edge・モバイルエミュレーターを1つのAPIでサポートする最新E2Eテストフレームワークです。並列実行・自動待機・トレースビューワー・コード生成が充実しています。

// tests/checkout.spec.ts: PlaywrightでEコマースのチェックアウトフローをテスト
import { test, expect, Page } from '@playwright/test'

// テストフィクスチャーで共通のセットアップを再利用
test.use({ baseURL: 'http://localhost:3000' })

test.beforeEach(async ({ page }) => {
  // テストごとにログイン状態を設定
  await page.goto('/login')
  await page.fill('[name="email"]', 'test@example.com')
  await page.fill('[name="password"]', 'password123')
  await page.click('button[type="submit"]')
  await page.waitForURL('/dashboard')
})

test('商品をカートに追加してチェックアウトできる', async ({ page }) => {
  // 商品一覧ページに移動
  await page.goto('/products')
  await expect(page).toHaveTitle(/商品一覧/)

  // 特定の商品を検索
  await page.fill('[data-testid="search-input"]', 'Tシャツ')
  await page.keyboard.press('Enter')
  await expect(page.locator('[data-testid="product-card"]')).toHaveCount(5)

  // 最初の商品をカートに追加
  const firstProduct = page.locator('[data-testid="product-card"]').first()
  const productName = await firstProduct.locator('h2').textContent()
  await firstProduct.locator('[data-testid="add-to-cart"]').click()

  // カートバッジが更新されることを確認
  await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1')

  // チェックアウトページへ
  await page.goto('/checkout')
  await expect(page.locator('[data-testid="cart-item"]')).toContainText(productName!)

  // 決済情報を入力
  await page.fill('[name="card-number"]', '4242424242424242')
  await page.fill('[name="expiry"]', '12/28')
  await page.fill('[name="cvv"]', '123')

  // 注文確定
  await page.click('[data-testid="place-order"]')

  // 成功ページに遷移することを確認
  await expect(page).toHaveURL(/\/order-confirmation\//)
  await expect(page.locator('h1')).toContainText('ご注文ありがとうございます')
})

test('APIモックを使ったテスト(外部依存なし)', async ({ page }) => {
  // APIリクエストをインターセプトしてモック
  await page.route('**/api/products', async route => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify([
        { id: 1, name: 'テスト商品', price: 1000 },
      ]),
    })
  })

  await page.goto('/products')
  await expect(page.locator('[data-testid="product-card"]')).toHaveCount(1)
  await expect(page.locator('h2')).toContainText('テスト商品')
})

test('スクリーンショットで視覚的回帰テスト', async ({ page }) => {
  await page.goto('/')
  await expect(page).toHaveScreenshot('homepage.png', { threshold: 0.1 })
})
# playwright.config.ts: マルチブラウザ並列テスト設定
import { defineConfig, devices } from '@playwright/test'

export default defineConfig({
  testDir: './tests',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 4 : undefined,
  reporter: [['html'], ['junit', { outputFile: 'test-results.xml' }]],
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
    { name: 'Mobile Chrome', use: { ...devices['Pixel 5'] } },
    { name: 'Mobile Safari', use: { ...devices['iPhone 14'] } },
  ],
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
})

Cypress

2014年公開、TypeScript製のOSSです。GitHubスター47k+。リアルタイムリロード・タイムトラベルデバッグ・直感的なセレクターAPIが特徴のE2Eフレームワークです。ブラウザ内で直接実行されるためAJAXスタブ・クロック制御が容易です。

// cypress/e2e/auth.cy.ts: Cypressでの認証フローテスト
describe('認証フロー', () => {
  beforeEach(() => {
    cy.visit('/login')
  })

  it('正しい認証情報でログインできる', () => {
    cy.intercept('POST', '/api/auth/login', { fixture: 'auth-success.json' }).as('loginRequest')

    cy.get('[data-cy="email"]').type('user@example.com')
    cy.get('[data-cy="password"]').type('password123')
    cy.get('[data-cy="submit"]').click()

    cy.wait('@loginRequest')
    cy.url().should('include', '/dashboard')
    cy.get('[data-cy="user-menu"]').should('contain', 'user@example.com')
  })

  it('間違ったパスワードでエラーが表示される', () => {
    cy.intercept('POST', '/api/auth/login', { statusCode: 401, body: { message: '認証に失敗しました' } })

    cy.get('[data-cy="email"]').type('user@example.com')
    cy.get('[data-cy="password"]').type('wrongpassword')
    cy.get('[data-cy="submit"]').click()

    cy.get('[data-cy="error-message"]').should('be.visible').and('contain', '認証に失敗しました')
  })

  // カスタムコマンドで繰り返しコードを共通化
  it('カスタムコマンドでログイン', () => {
    cy.loginByApi('user@example.com', 'password123')
    cy.visit('/dashboard')
    cy.get('[data-cy="welcome"]').should('be.visible')
  })
})

Puppeteer

2017年公開(Google Chrome Team)、TypeScript製のOSSです。GitHubスター88k+。Chrome DevTools Protocolを直接操作するChromeヘッドレス自動化ライブラリで、スクリーンショット生成・PDF変換・Web scraping・パフォーマンス計測に特化しています。

// puppeteer: PDFレポート生成とWebスクレイピング
import puppeteer from 'puppeteer'

const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()

// ダッシュボードをPDFに変換
await page.goto('http://localhost:3000/dashboard', { waitUntil: 'networkidle0' })
await page.pdf({ path: 'report.pdf', format: 'A4', printBackground: true })

await browser.close()

機能比較表

比較項目PlaywrightCypressPuppeteer
ブラウザサポート✅ 全ブラウザ△(Chrome・FF・Edge)Chrome特化
並列実行✅ 高速△(有料Cloud)
リアルタイムデバッグ
コード生成
PDF/スクリーンショット✅ 最強

E2EテストはDevOpsカテゴリ/categories/devopsのGitHub Actions・GitLab CIに統合してプルリクエストごとに自動実行してカバレッジと品質レポートをPRコメントに投稿します。LLM Toolsカテゴリ/categories/llm-toolsのClaude APIと組み合わせて「テスト失敗時にスクリーンショットをAIが分析してバグの原因を提案する」AI支援デバッグパイプラインも構築できます。

FAQ

Q. PlaywrightをGitHub Actionsで実行するには?

A. mcr.microsoft.com/playwright:v1.48.0-jammy公式Dockerイメージを使うのが最も確実です。.github/workflows/e2e.yml設定: uses: actions/setup-node@v4npm cinpx playwright install --with-depsnpx playwright testuses: actions/upload-artifact@v4でHTMLレポートをアーティファクトとして保存。キャッシュ最適化: ~/.cache/ms-playwrightをActionsキャッシュに保存してブラウザダウンロードをスキップ。分散並列化: shardIndexshardTotalオプションでテストを複数ジョブに分割して並列実行→合計実行時間を削減します。

Q. CypressとPlaywrightはどちらを選べばいいですか?

A. チームのDevX・リアルタイムデバッグ・既存資産ならCypressクロスブラウザ・モバイル・並列高速化・新規プロジェクトならPlaywrightが向いています。Playwright優位: ①Firefox・WebKitをサポートしてSafari互換性を自動検証②並列実行が標準(Cypressは有料Cloud)③Trace Viewerが優秀でテスト失敗時のデバッグが容易④page.route()でAPI mockが強力。Cypress優位: ①テスト実行画面がリアルタイムに表示されてステップを視覚的に確認②cy.intercept()の構文がPlaywrightより直感的③コミュニティプラグインが豊富④Component Testing(React/Vueの単体テスト)にも対応。

Q. PlaywrightでAxe(アクセシビリティ検査)を統合するには?

A. @axe-core/playwrightパッケージを追加して全ページのWCAG準拠を自動検証します。①npm install @axe-core/playwright②テスト内でconst accessibilityScanResults = await new AxeBuilder({ page }).analyze()expect(accessibilityScanResults.violations).toEqual([])でバイオレーションがないことをアサート。特定ルールのみ検査: .include('#main-content')でスコープを絞って.withTags(['wcag2a', 'wcag2aa'])でWCAG 2.2レベルAAを検査できます。CI統合: アクセシビリティ違反をJUnitレポートとして出力してPRに自動コメントするパターンが普及しています。

Q. Playwrightのコード生成機能(Codegen)の使い方は?

A. npx playwright codegen <URL>でブラウザが起動してクリック・タイピング操作が自動的にTypeScriptコードに変換されます。起動: npx playwright codegen http://localhost:3000→ブラウザが開いてInspectorウィンドウが並んで表示。操作: ブラウザで実際にクリック・フォーム入力→Inspectorにリアルタイムでコードが生成。ロケーター最適化: PlaywrightはARIA role・data-testidplaceholderlabelの優先度でセレクターを自動選択(CSSセレクター・XPathより壊れにくい)。生成後: 生成コードをコピーして.spec.tsファイルに貼り付けて調整。自動生成コードは完璧ではないためawait expect(page.locator(...)).toBeVisible()などのアサーションを手動で追加します。

まとめ

ユースケース推奨ツール
クロスブラウザ・並列・CI高速化Playwright
リアルタイムデバッグ・コンポーネントテストCypress
スクリーンショット・PDF生成・スクレイピングPuppeteer

関連外部リソース

他の記事も読む

Let's Build Together

OSS導入、自社だけで悩まない。

ツール選定から構築・運用・AI活用まで、オープンソースラボ運営元のClasslessが伴走します。初回のご相談は無料です。