CheatSheet
日本語 icon日本語English iconEnglish
チートシートとはカンニングペーパーのことです。それが転じて、本来覚えることをまとめておいたものです。
要点をすぐに参照できるようにまとめてみました。

Playwright

エンジニアのためのWebチートシート

Playwrightは、Microsoftが開発したモダンなE2Eテストフレームワークです。 Chromium、Firefox、WebKitのクロスブラウザテスト、Auto-wait、ロケーター、アサーション、テストランナー、設定ファイル、スクリーンショット、トレースなどをチートシートにまとめました。

セットアップ & CLI

インストール

  • Playwrightのセットアップ方法です。

    # Create new project with Playwright
    npm init playwright@latest
    
    # Or add to existing project
    npm install -D @playwright/test
    npx playwright install
    

CLIコマンド

コマンド説明
npx playwright test全テストを実行します。
npx playwright test tests/login.spec.ts特定のテストファイルを実行します。
npx playwright test --grep "login"テスト名でフィルタして実行します。
npx playwright test --headedブラウザを表示してテストを実行します。
npx playwright test --uiUIモードでテストを実行します(インタラクティブ)。
npx playwright test --debugデバッグモードでテストを実行します。
npx playwright test --project=chromium特定のブラウザプロジェクトのみ実行します。
npx playwright codegen https://example.comブラウザ操作を記録してテストコードを自動生成します。
npx playwright show-reportHTMLテストレポートを開きます。
npx playwright installテスト用ブラウザをインストールします。
npx playwright install-depsシステム依存パッケージをインストールします。
npx playwright test --listテストの一覧を表示します(実行しない)。

ロケーター

推奨ロケーター

ロケーター説明
getByRoleアクセシブルロールで要素を検索(最も推奨)page.getByRole('button', { name: 'Submit' })
getByTextテキスト内容で検索page.getByText('Hello World')
getByLabelフォームラベルで検索page.getByLabel('Email')
getByPlaceholderプレースホルダーで検索page.getByPlaceholder('Enter email')
getByTestIddata-testid属性で検索page.getByTestId('submit-btn')
getByAltTextalt属性で画像を検索page.getByAltText('Logo')
getByTitletitle属性で検索page.getByTitle('Settings')

CSS / XPath セレクター

  • 推奨ロケーターで対応できない場合に使用します。

    // CSS selector
    page.locator('.submit-button')
    page.locator('#email-input')
    page.locator('[data-cy="login"]')
    page.locator('article >> .title')
    
    // XPath
    page.locator('xpath=//button[@type="submit"]')
    
    // nth element
    page.locator('.item').nth(2)
    page.locator('.item').first()
    page.locator('.item').last()

ロケーターの連鎖

  • ロケーターをチェインして絞り込むパターンです。

    // Filter by text
    page.getByRole('listitem')
      .filter({ hasText: 'Product' })
    
    // Filter by child locator
    page.getByRole('listitem')
      .filter({
        has: page.getByRole('heading', { name: 'Title' })
      })
    
    // Chain locators
    page.getByRole('dialog')
      .getByRole('button', { name: 'OK' })
    
    // Filter + action
    page.getByRole('row')
      .filter({ hasText: 'admin' })
      .getByRole('button', { name: 'Edit' })
      .click()

ページ操作

ナビゲーション

アクション説明
await page.goto('https://example.com')指定URLに移動します。
await page.goBack()ブラウザの「戻る」を実行します。
await page.goForward()ブラウザの「進む」を実行します。
await page.reload()ページをリロードします。

値の取得

アクション説明
await locator.textContent()要素のテキストコンテンツを取得します。
await locator.inputValue()入力フィールドの値を取得します。
await locator.getAttribute('href')要素の属性値を取得します。
await locator.innerHTML()要素のHTMLコンテンツを取得します。
await locator.isVisible()要素が表示されているかを確認します。
await locator.count()一致する要素の数を取得します。

要素操作

アクション説明
await locator.click()要素をクリックします。
await locator.dblclick()要素をダブルクリックします。
await locator.fill('text')入力フィールドに値を設定します(既存値をクリア)。
await locator.type('text')文字を1つずつ入力します。
await locator.check()チェックボックスをONにします。
await locator.uncheck()チェックボックスをOFFにします。
await locator.selectOption('value')ドロップダウンの値を選択します。
await locator.hover()要素の上にマウスカーソルを移動します。
await locator.focus()要素にフォーカスします。
await locator.press('Enter')キーボードキーを押します。
await locator.setInputFiles('file.pdf')ファイルをアップロードします。

アサーション

要素アサーション

アサーション説明
expect(locator).toBeVisible()要素が表示されていることを確認します。
expect(locator).toBeHidden()要素が非表示であることを確認します。
expect(locator).toBeEnabled()要素が有効であることを確認します。
expect(locator).toBeDisabled()要素が無効であることを確認します。
expect(locator).toHaveText('text')テキストが完全一致することを確認します。
expect(locator).toContainText('text')テキストが含まれていることを確認します。
expect(locator).toHaveValue('value')入力値が一致することを確認します。
expect(locator).toHaveAttribute('name', 'val')属性値が一致することを確認します。
expect(locator).toHaveClass(/active/)CSSクラスが含まれていることを確認します。
expect(locator).toHaveCount(3)要素の数が一致することを確認します。
expect(locator).toBeChecked()チェックボックスがONであることを確認します。

ページアサーション

アサーション説明
expect(page).toHaveTitle(/Dashboard/)ページタイトルが一致することを確認します。
expect(page).toHaveURL(/dashboard/)URLが一致することを確認します。
expect(page).toHaveScreenshot()スクリーンショットがベースラインと一致することを確認します。

テストランナー

テスト構造

  • @playwright/test の基本的なテスト構造です。

    import { test, expect } from '@playwright/test';
    
    test.describe('Login', () => {
      test('valid credentials', async ({ page }) => {
        await page.goto('/login');
        await page.getByLabel('Email').fill('user@test.com');
        await page.getByLabel('Password').fill('pass123');
        await page.getByRole('button', { name: 'Login' }).click();
        await expect(page).toHaveURL('/dashboard');
      });
    
      test('invalid credentials', async ({ page }) => {
        await page.goto('/login');
        await page.getByLabel('Email').fill('wrong@test.com');
        await page.getByLabel('Password').fill('wrong');
        await page.getByRole('button', { name: 'Login' }).click();
        await expect(page.getByText('Invalid credentials')).toBeVisible();
      });
    });

カスタムFixtures

  • 再利用可能なセットアップロジックを定義するパターンです。

    import { test as base } from '@playwright/test';
    
    const test = base.extend<{ loggedInPage: Page }>({
      loggedInPage: async ({ page }, use) => {
        await page.goto('/login');
        await page.getByLabel('Email').fill('admin@test.com');
        await page.getByLabel('Password').fill('admin');
        await page.getByRole('button', { name: 'Login' }).click();
        await use(page);
      },
    });
    // Use fixture in test
    test('dashboard', async ({ loggedInPage }) => {
      await expect(loggedInPage).toHaveURL('/dashboard');
    });

テスト制御

  • テストのスキップや条件付き実行のパターンです。

    // Skip a test
    test.skip('feature not ready', async () => {});
    
    // Run only this test
    test.only('debug this', async ({ page }) => {});
    
    // Conditional skip
    test('mobile only', async ({ page, isMobile }) => {
      test.skip(!isMobile, 'Mobile only test');
      // ...
    });
    
    // Slow test (3x timeout)
    test('complex flow', async ({ page }) => {
      test.slow();
      // ...
    });

設定ファイル

基本設定

  • playwright.config.ts の主要な設定項目です。

    // playwright.config.ts
    import { defineConfig, devices } from
      '@playwright/test';
    
    export default defineConfig({
      testDir: './tests',
      timeout: 30_000,
      retries: process.env.CI ? 2 : 0,
      workers: process.env.CI ? 1 : undefined,
      fullyParallel: true,
      reporter: [
        ['html'],
        ['json', { outputFile: 'results.json' }],
      ],
      use: {
        baseURL: 'http://localhost:3000',
        viewport: { width: 1280, height: 720 },
        locale: 'ja-JP',
        timezoneId: 'Asia/Tokyo',
        screenshot: 'only-on-failure',
        trace: 'on-first-retry',
        actionTimeout: 10_000,
      },
    });

ブラウザプロジェクト設定

  • 複数ブラウザでのテスト実行設定です。

    // playwright.config.ts (projects section)
    projects: [
      { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
      { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
      { name: 'webkit', use: { ...devices['Desktop Safari'] } },
      { name: 'mobile', use: { ...devices['iPhone 13'] } },
    ],

Webサーバー自動起動

  • テスト前に開発サーバーを自動起動する設定です。

    // playwright.config.ts
    webServer: {
      command: 'npm run dev',
      url: 'http://localhost:3000',
      reuseExistingServer: !process.env.CI,
      timeout: 120_000,
    },

スクリーンショット & トレース

スクリーンショット

  • テスト中にスクリーンショットを取得するパターンです。

    // Full page
    await page.screenshot({ path: 'full.png', fullPage: true });
    
    // Element only
    await page.getByRole('main').screenshot({ path: 'main.png' });
    
    // With clip region
    await page.screenshot({
      path: 'clip.png',
      clip: { x: 0, y: 0, width: 800, height: 600 },
    });

トレース

  • テスト実行の詳細なトレースを記録するパターンです。

    // Start tracing
    await context.tracing.start({
      screenshots: true, snapshots: true, sources: true,
    });
    
    // ... run test actions ...
    
    // Stop and save
    await context.tracing.stop({ path: 'trace.zip' });
    // View: npx playwright show-trace trace.zip

ビジュアルリグレッションテスト

  • スクリーンショットベースのUI回帰テストです。

    // Visual comparison test
    await expect(page).toHaveScreenshot(
      'homepage.png'
    );
    
    // With threshold
    await expect(page).toHaveScreenshot(
      'homepage.png',
      { maxDiffPixelRatio: 0.01 }
    );
    
    // Update baselines:
    // npx playwright test --update-snapshots

ベストプラクティス

推奨プラクティス

プラクティス
ユーザーの行動をテストする(実装の詳細ではなく)
CSSセレクターよりgetByRole等の意味的ロケーターを優先する
page.waitForTimeout()やsleepを使わない(Auto-waitを活用)
Page Object Model (POM) パターンでテストコードを整理する
beforeEachよりFixturesを使って共通セットアップを定義する
テストは並列実行できるよう独立させる
各テストでBrowser Contextを分離する(Cookie/Storage独立)
Web-firstアサーション(自動リトライ付き)を使う