mcpField
P
playwright-expert

playwright-expert

github.com/cin12211テスト・品質22658 回インストール4 日前に更新
リポジトリ

playwright-expert について

playwright-expert は、Playwright によるエンドツーエンドテストとブラウザー自動化のスキルです。テストの導入や問題への対処、テストコードのレビューを支援します。

主な機能

  1. 01Playwright のセットアップ案内
  2. 02エンドツーエンドテスト例
  3. 03Page Object Model の案内
  4. 04ネットワークの傍受とモック
  5. 05ビジュアル回帰チェック
  6. 06不安定なテストへの対処

活用シーン

  1. 01プロジェクトで Playwright テストを開始
  2. 02ログインなどのユーザーフローをテスト
  3. 03ブラウザーテストで API 応答をモック
  4. 04テストの信頼性に関するレビュー

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/cin12211/orca-q --skill playwright-expert

インストール後、Claude Code で/playwright-expertを入力して読み込まれたか確認します。

詳細

Playwright エキスパート

E2E テスト、ブラウザー自動化、クロスブラウザーテストに関する Playwright の専門家です。

呼び出されたとき

専門家を推奨
  • ユニット/統合テスト:jest-expert または vitest-expert を推奨します
  • React コンポーネントのテスト:testing-expert を推奨します
  • API テストのみ:rest-api-expert を推奨します
環境の検出
npx playwright --version 2>/dev/null
ls playwright.config.* 2>/dev/null
find . -name "*.spec.ts" -path "*e2e*" | head -5

問題別プレイブック

プロジェクトのセットアップ
# Initialize Playwright
npm init playwright@latest

# Install browsers
npx playwright install
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: 'html',
  use: {
    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'] } },
  ],
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});
テストの作成
import { test, expect } from '@playwright/test';

test.describe('Authentication', () => {
  test('should login successfully', async ({ page }) => {
    await page.goto('/login');
    
    await page.fill('[data-testid="email"]', '[email protected]');
    await page.fill('[data-testid="password"]', 'password123');
    await page.click('[data-testid="submit"]');
    
    await expect(page).toHaveURL('/dashboard');
    await expect(page.locator('h1')).toContainText('Welcome');
  });

  test('should show error for invalid credentials', async ({ page }) => {
    await page.goto('/login');
    
    await page.fill('[data-testid="email"]', '[email protected]');
    await page.fill('[data-testid="password"]', 'wrong');
    await page.click('[data-testid="submit"]');
    
    await expect(page.locator('.error-message')).toBeVisible();
  });
});
ページオブジェクトモデル
// pages/login.page.ts
import { Page, Locator } from '@playwright/test';

export class LoginPage {
  readonly page: Page;
  readonly emailInput: Locator;
  readonly passwordInput: Locator;
  readonly submitButton: Locator;

  constructor(page: Page) {
    this.page = page;
    this.emailInput = page.locator('[data-testid="email"]');
    this.passwordInput = page.locator('[data-testid="password"]');
    this.submitButton = page.locator('[data-testid="submit"]');
  }

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

  async login(email: string, password: string) {
    await this.emailInput.fill(email);
    await this.passwordInput.fill(password);
    await this.submitButton.click();
  }
}

// Usage in test
test('login test', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.goto();
  await loginPage.login('[email protected]', 'password');
});
ネットワークのインターセプト
test('mock API response', async ({ page }) => {
  await page.route('**/api/users', async (route) => {
    await route.fulfill({
      status: 200,
      body: JSON.stringify([{ id: 1, name: 'Mock User' }]),
    });
  });

  await page.goto('/users');
  await expect(page.locator('.user-name')).toContainText('Mock User');
});
ビジュアルリグレッション
test('visual comparison', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png', {
    maxDiffPixelRatio: 0.1,
  });
});
不安定なテストへの対処
// Retry flaky tests
test('flaky network test', async ({ page }) => {
  test.slow(); // Triple timeout
  
  await page.goto('/');
  await page.waitForLoadState('networkidle');
  
  // Use polling assertions
  await expect(async () => {
    const response = await page.request.get('/api/status');
    expect(response.ok()).toBeTruthy();
  }).toPass({ timeout: 10000 });
});

テストの実行

# Run all tests
npx playwright test

# Run specific file
npx playwright test login.spec.ts

# Run in headed mode
npx playwright test --headed

# Run in UI mode
npx playwright test --ui

# Debug mode
npx playwright test --debug

# Generate report
npx playwright show-report

コードレビューのチェックリスト

  • セレクターに data-testid 属性を使用する
  • 複雑なフローにはページオブジェクトモデルを使用する
  • 必要に応じてネットワークリクエストをモックする
  • 適切な待機方法を使用する(任意の待機時間を設定しない)
  • 失敗時のスクリーンショットを設定する
  • 並列実行を有効にする

アンチパターン

  1. ハードコードされた待機時間 - 適切なアサーションを使用する
  2. 壊れやすいセレクター - data-testid を使用する
  3. テスト間で状態を共有する - テストを分離する
  4. CI でリトライしない - 不安定さに対処するためリトライを追加する
  5. 実装の詳細をテストする - ユーザーの操作をテストする

コメント