mcpField
W
webapp-testing

webapp-testing

github.com/pixel-process-ugテスト・品質382 回インストール33 週間前に更新
リポジトリ

webapp-testing について

webapp-testingは、PlaywrightでWebアプリをテストするためのスキルです。開発者向けに、エンドツーエンドテスト、画面検証、アクセシビリティ監査、ネットワークのモック、モバイル表示の確認を案内します。

主な機能

  1. 01Playwrightによるエンドツーエンドテスト
  2. 02スクリーンショットとビジュアル回帰検証
  3. 03ブラウザーコンソールエラーの分析
  4. 04axe-coreによるアクセシビリティ監査
  5. 05ネットワークリクエストのモック
  6. 06モバイルビューポートのテスト

活用シーン

  1. 01重要なユーザーフローの検証
  2. 02変更時のページレイアウト確認
  3. 03ページのアクセシビリティ監査
  4. 04モバイルでのレスポンシブ動作のテスト

インストール

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

$npx skills add https://github.com/pixel-process-ug/superkit-agents --skill webapp-testing

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

詳細

Web アプリのテスト

概要

Playwright を主なツールとして、包括的な Web アプリケーションのテストを行います。このスキルでは、視覚的な検証のためのスクリーンショットの撮影、ブラウザーのコンソールログの分析、ユーザー操作のシミュレーション、ビジュアルリグレッションテスト、axe-core によるアクセシビリティ監査、ネットワークリクエストのモック、モバイルのビューポートテストなど、エンドツーエンドのテストワークフローを扱います。

開始時に伝えること:「Playwright ベースの Web アプリケーションテストに webapp-testing スキルを使用します。」


フェーズ 1:テスト計画

目標: テスト対象を特定し、インフラストラクチャを準備します。

アクション
  1. テストする重要なユーザーフローを特定する
  2. テスト環境とビューポートを定義する
  3. テストフィクスチャとデータを準備する
  4. Playwright のプロジェクト設定を構成する
  5. ビジュアルベースラインのスクリーンショットを用意する
ユーザーフローの優先度判断表
フローの種類優先度テストの深さ
認証(ログイン/ログアウト/登録)重大正常系とエラー系の全パス
中核的なビジネスワークフロー(購入、送信)重大正常系、エラー系、エッジケースの全パス
ナビゲーションとルーティング高主要なルートすべて
検索とフィルタリング高一般的なクエリと空の状態
設定とプロフィール中正常系
管理者/バックオフィス中主要な操作のみ
停止 — 以下を満たすまでフェーズ 2 に進まないでください:
  • 重要なユーザーフローを特定し、優先順位を付けている
  • テスト環境とビューポートを定義している
  • Playwright の設定が整っている
  • テストデータの方針を定義している

フェーズ 2:テストの実装

目標: ページオブジェクトモデルとアクセシブルなロケーターを使ってテストを記述します。

アクション
  1. 主要なページのページオブジェクトモデルを作成する
  2. エンドツーエンドのテストシナリオを実装する
  3. ビジュアルリグレッション用のスナップショットを追加する
  4. アクセシビリティチェックを統合する
  5. 独立したテスト用にネットワークモックを設定する
Playwright の設定
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './tests/e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: [
    ['html', { open: 'never' }],
    ['junit', { outputFile: 'test-results/junit.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 13'] } },
  ],
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
  },
});
ページオブジェクトモデル
class LoginPage {
  constructor(private page: Page) {}

  readonly emailInput = this.page.getByLabel('Email');
  readonly passwordInput = this.page.getByLabel('Password');
  readonly submitButton = this.page.getByRole('button', { name: 'Sign in' });
  readonly errorMessage = this.page.getByRole('alert');

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

  async expectError(message: string) {
    await expect(this.errorMessage).toContainText(message);
  }
}
ロケーター選択の判断表
ロケーターの種類優先度使用する場面
getByRole第 1 選択肢ARIA ロール(ボタン、リンク、見出し)を持つ要素
getByLabel第 2 選択肢ラベル付きのフォームフィールド
getByPlaceholder第 3 選択肢表示ラベルのないフィールド
getByText第 4 選択肢操作対象ではない表示テキスト
getByTestId最終手段アクセシブルなロケーターが使えない場合
CSS セレクター/XPath使用しないスタイルの変更で壊れるため
停止 — 以下を満たすまでフェーズ 3 に進まないでください:
  • 主要なページのページオブジェクトモデルが存在する
  • テストではアクセシブルなロケーターのみを使用している
  • ビジュアルベースラインを確立している
  • アクセシビリティチェックを統合している
  • 独立したテスト用にネットワークモックを設定している

フェーズ 3:CI への統合

目標: CI で信頼性が高く高速なテスト実行を設定します。

アクション
  1. ヘッドレスブラウザーでの実行を設定する
  2. スクリーンショットのアーティファクト収集を準備する
  3. リトライと不安定なテストの検出を設定する
  4. レポート機能を追加する(HTML レポート、JUnit XML)
  5. ビジュアル差分のレビュー手順を準備する
CI 設定チェックリスト
  • CI でテストがヘッドレス実行される
  • リトライが有効になっている(CI では 2 回リトライ)
  • 失敗時にスクリーンショットと動画のアーティファクトが収集される
  • CI 連携用の JUnit XML が出力される
  • 手動レビュー用の HTML レポートが生成される
  • マージ前にビジュアル差分のスナップショットをレビューする
停止 — 以下を満たせば CI への統合は完了です:
  • CI パイプラインでテストが安定して実行される
  • 失敗時にアーティファクトが収集される
  • 不安定なテストを特定して修正している(スキップしていない)

スクリーンショット撮影のパターン

ページ全体
test('homepage renders correctly', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png', {
    fullPage: true,
    maxDiffPixelRatio: 0.01,
  });
});
要素単位
test('navigation bar matches design', async ({ page }) => {
  await page.goto('/');
  const nav = page.getByRole('navigation');
  await expect(nav).toHaveScreenshot('navbar.png');
});
動的コンテンツのマスキング
test('dashboard layout', async ({ page }) => {
  await page.goto('/dashboard');
  await expect(page).toHaveScreenshot('dashboard.png', {
    mask: [
      page.locator('[data-testid="timestamp"]'),
      page.locator('[data-testid="user-avatar"]'),
      page.locator('.chart-container'),
    ],
    animations: 'disabled',
  });
});

ブラウザーログの分析

test('no console errors on page load', async ({ page }) => {
  const consoleErrors: string[] = [];

  page.on('console', msg => {
    if (msg.type() === 'error') consoleErrors.push(msg.text());
  });
  page.on('pageerror', error => {
    consoleErrors.push(error.message);
  });

  await page.goto('/');
  await page.waitForLoadState('networkidle');
  expect(consoleErrors).toEqual([]);
});

axe-core によるアクセシビリティテスト

import AxeBuilder from '@axe-core/playwright';

test('page has no accessibility violations', async ({ page }) => {
  await page.goto('/');
  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa', 'wcag21aa'])
    .exclude('.third-party-widget')
    .analyze();
  expect(results.violations).toEqual([]);
});

ネットワークリクエストのモック

test('displays users from API', async ({ page }) => {
  await page.route('**/api/users', async route => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify([{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]),
    });
  });
  await page.goto('/users');
  await expect(page.getByText('Alice')).toBeVisible();
});

test('handles API errors gracefully', async ({ page }) => {
  await page.route('**/api/users', route =>
    route.fulfill({ status: 500, body: 'Internal Server Error' })
  );
  await page.goto('/users');
  await expect(page.getByText('Something went wrong')).toBeVisible();
});

モバイルのビューポートテスト

test.describe('mobile responsive', () => {
  test.use({ viewport: { width: 375, height: 667 } });

  test('hamburger menu works', async ({ page }) => {
    await page.goto('/');
    await expect(page.getByRole('navigation')).not.toBeVisible();
    await page.getByRole('button', { name: 'Menu' }).click();
    await expect(page.getByRole('navigation')).toBeVisible();
  });
});

テストの構成

tests/
  e2e/
    auth/
      login.spec.ts
      register.spec.ts
    checkout/
      cart.spec.ts
      payment.spec.ts
    fixtures/
      test-data.ts
      auth.setup.ts
    pages/
      login.page.ts
      dashboard.page.ts
    utils/
      helpers.ts

アンチパターン/よくある間違い

アンチパターン問題である理由正しいアプローチ
CSS セレクターまたは XPathスタイルの変更で動作しなくなりますアクセシブルなロケーター(ロール、ラベル、テキスト)を使用します
page.waitForTimeout()根拠のない遅延が発生し、テストが不安定になりますexpect().toBeVisible() などを使用します
サードパーティーコンポーネントの詳細なテストテスト対象のコードではありません内部実装ではなく、連携部分をテストします
テストデータのハードコード環境をまたぐと動作しなくなりますフィクスチャとファクトリーを使用します
実行順序に依存するテスト壊れやすく、デバッグが困難です各テストは独立している必要があります
不安定なテストを放置するテストスイートへの信頼が損なわれます根本原因を修正するか、隔離します
動的コンテンツをマスクしないスクリーンショット常に差異が生じ、常に失敗しますタイムスタンプ、アバター、グラフをマスクします
アクセシビリティチェックがない重要な品質ゲートが抜け落ちますすべてのページで axe-core を使用します

統合ポイント

スキル関係
senior-frontendフロントエンドコンポーネントは E2E テストでテストします
testing-strategyE2E テストはテストピラミッドの頂点です
acceptance-testingユーザーフローテストは受け入れテストとして機能します
performance-optimizationパフォーマンス予算は E2E テストで検証できます
code-reviewテストでアクセシブルなロケーターが使われているかをレビューします
security-reviewセキュリティヘッダーと認証フローを E2E テストで検証します

品質チェックリスト

  • 重要なユーザーフローをすべてカバーしている
  • テストでアクセシブルなロケーター(ロール、ラベル、テキスト)を使用している
  • テストを分離するためにネットワークをモックしている
  • ビジュアルリグレッションのベースラインをレビューし、承認している
  • すべてのページでアクセシビリティスキャンを実施している
  • レスポンシブ機能について、モバイルビューポートでテストしている
  • waitForTimeout を使用していない(適切なアサーションを使用する)
  • CI パイプラインでリトライを設定している
  • 失敗時にスクリーンショットの成果物を収集している
  • 不安定なテストを特定して修正している(スキップしていない)

スキルタイプ

FLEXIBLE — プロジェクトの重要なパスに合わせてテストの深さを調整します。ページオブジェクトモデルのパターンとアクセシブルなロケーターを強く推奨します。すべてのページでアクセシビリティチェックを必須とします。マージ前にビジュアルリグレッションのベースラインをレビューする必要があります。

コメント