T-CREATOR

Playwright MCP 活用事例集:現場で効く業務効率化テクニック

Playwright MCP 活用事例集:現場で効く業務効率化テクニック

現場で働く開発者の皆様、日々のテスト作業に追われていませんか?リリース前の動作確認で深夜まで作業し、手動テストの繰り返しに疲れを感じている方も多いのではないでしょうか。

そんな課題を解決する強力なツールとして、Playwright MCP が注目を集めています。本記事では、実際の現場で効果を発揮した活用事例を中心に、業務効率化のための具体的なテクニックをご紹介します。

背景

従来のテスト自動化の課題

開発現場では、品質保証のためのテストが欠かせません。しかし、従来のテスト自動化には以下のような課題がありました。

複雑な設定とメンテナンス 既存のテストツールは設定が複雑で、新しいメンバーが参加するたびに学習コストが発生していました。また、UI の変更に対してテストコードの修正が頻繁に必要になり、メンテナンス作業が大きな負担となっていました。

ブラウザ間の互換性問題 異なるブラウザでの動作確認は手動で行うことが多く、Chrome、Firefox、Safari でそれぞれ異なる挙動を示すことがありました。この問題により、本番環境でのバグ発見が遅れるケースが発生していました。

テスト実行の不安定性 ネットワーク遅延やページの読み込み速度により、テストが不安定になることがありました。特に、以下のようなエラーが頻発していました。

javascript// よくある不安定なテストの例
await page.click('#submit-button');
await page.waitForSelector('.success-message'); // ここで失敗することが多い

MCP が注目される理由

MCP(Model Context Protocol)は、AI と外部システムの連携を標準化するプロトコルです。このプロトコルがテスト自動化分野で注目される理由は、以下の点にあります。

統一されたインターフェース MCP により、異なるツールやシステム間でのデータ交換が標準化されます。これにより、テストツール間の連携がスムーズになり、効率的なテスト環境の構築が可能になります。

AI 活用による自動化の向上 MCP を通じて AI がテストシナリオを理解し、より賢いテスト自動化を実現できます。従来の固定的なテストシナリオから、動的で柔軟なテストへの進化が期待できます。

Playwright MCP の基本概念

MCP の仕組み

MCP は、AI モデルとクライアントアプリケーション間のコミュニケーションを標準化するプロトコルです。Playwright MCP では、この仕組みを活用してテスト自動化を行います。

以下は、MCP の基本的な通信フローです:

typescript// MCP サーバーの基本設定
interface MCPServer {
  name: string;
  version: string;
  capabilities: {
    resources?: boolean;
    tools?: boolean;
    prompts?: boolean;
  };
}

// Playwright MCP の初期化
const mcpServer: MCPServer = {
  name: 'playwright-mcp',
  version: '1.0.0',
  capabilities: {
    resources: true,
    tools: true,
    prompts: true,
  },
};

この設定により、MCP サーバーが Playwright の機能を外部システムに提供できるようになります。

Playwright との連携メリット

Playwright MCP を使用することで、以下のメリットが得られます:

自然言語によるテスト記述 従来のプログラミング言語だけでなく、自然言語でテストシナリオを記述できるようになります。これにより、非技術者でもテストの意図を理解しやすくなります。

yaml# 自然言語によるテストシナリオ例
test_scenario:
  description: 'ユーザーログイン機能のテスト'
  steps:
    - 'トップページにアクセス'
    - 'ログインボタンをクリック'
    - 'ユーザー名とパスワードを入力'
    - 'ログイン成功を確認'

動的なテスト実行 AI がページの状態を理解し、適切なタイミングでテストを実行できます。これにより、従来の待機時間を調整する必要がなくなり、より安定したテストが実現できます。

現場での活用事例

Web アプリケーションテスト自動化

実際の現場では、EC サイトの商品購入フローテストで大きな効果を発揮しました。従来は手動で 30 分かかっていたテストが、以下のコードにより 5 分で完了するようになりました。

typescript// 商品購入フローの自動化テスト
import { test, expect } from '@playwright/test';

test('商品購入フロー', async ({ page }) => {
  // 商品ページへアクセス
  await page.goto('/product/123');

  // 商品をカートに追加
  await page.click('[data-testid="add-to-cart"]');

  // カート画面へ遷移
  await page.click('[data-testid="cart-icon"]');

  // 購入手続きへ進む
  await page.click('[data-testid="checkout-button"]');

  // 配送情報を入力
  await page.fill(
    '[data-testid="shipping-address"]',
    'Tokyo'
  );
  await page.fill(
    '[data-testid="phone-number"]',
    '090-1234-5678'
  );
});

このテストコードは、商品の追加から購入手続きまでの一連の流れを自動化しています。特に重要なのは、data-testid属性を使用して UI の変更に強いテストを作成している点です。

続けて、エラーハンドリングの部分も実装しました:

typescript// エラーハンドリングを含むテスト
test('商品購入フロー - エラーケース', async ({ page }) => {
  try {
    await page.goto('/product/123');

    // 在庫切れの場合の処理
    const stockStatus = await page.locator(
      '[data-testid="stock-status"]'
    );
    if ((await stockStatus.textContent()) === '在庫切れ') {
      console.log('在庫切れのため、テストをスキップします');
      return;
    }

    await page.click('[data-testid="add-to-cart"]');
  } catch (error) {
    // よくあるエラーの例
    if (error.message.includes('Target closed')) {
      console.error('ページが予期せず閉じられました');
    } else if (error.message.includes('Timeout')) {
      console.error('タイムアウトエラーが発生しました');
    }
    throw error;
  }
});

API 連携テストの効率化

フロントエンドとバックエンドの連携テストでも、大きな効果を発揮しました。以下は、ユーザー認証 API との連携テストの例です:

typescript// API連携テストの例
import { test, expect } from '@playwright/test';

test.describe('ユーザー認証API連携テスト', () => {
  test('ログイン成功パターン', async ({
    page,
    request,
  }) => {
    // APIエンドポイントへの直接リクエスト
    const response = await request.post('/api/auth/login', {
      data: {
        username: 'testuser',
        password: 'testpass123',
      },
    });

    // APIレスポンスの確認
    expect(response.status()).toBe(200);
    const responseData = await response.json();
    expect(responseData.token).toBeDefined();

    // フロントエンドでの確認
    await page.goto('/dashboard');
    await page.waitForSelector(
      '[data-testid="user-profile"]'
    );

    const userProfile = await page.locator(
      '[data-testid="user-profile"]'
    );
    expect(await userProfile.textContent()).toContain(
      'testuser'
    );
  });
});

このテストでは、API の直接テストとフロントエンドの表示確認を組み合わせています。これにより、データの整合性を保ちながら、ユーザー体験も含めた総合的なテストが可能になります。

エラーケースのテストも重要です:

typescript// APIエラーケースのテスト
test('ログイン失敗パターン', async ({ page, request }) => {
  // 間違った認証情報でのテスト
  const response = await request.post('/api/auth/login', {
    data: {
      username: 'wronguser',
      password: 'wrongpass',
    },
  });

  expect(response.status()).toBe(401);
  const errorData = await response.json();

  // 実際のエラーメッセージの例
  expect(errorData.error).toBe('Invalid credentials');
  expect(errorData.message).toBe(
    'ユーザー名またはパスワードが間違っています'
  );
});

回帰テストの高速化

機能追加や修正のたびに実行する回帰テストも、大幅に効率化できました。以下は、並列実行を活用した回帰テストの例です:

typescript// 並列実行による回帰テスト
import { test, devices } from '@playwright/test';

// 複数ブラウザでの同時実行設定
const browserConfigs = [
  { name: 'Chrome', use: { ...devices['Desktop Chrome'] } },
  {
    name: 'Firefox',
    use: { ...devices['Desktop Firefox'] },
  },
  { name: 'Safari', use: { ...devices['Desktop Safari'] } },
];

browserConfigs.forEach((config) => {
  test.describe(`回帰テスト - ${config.name}`, () => {
    test.use(config.use);

    test('主要機能のテスト', async ({ page }) => {
      // 各ブラウザで同じテストを実行
      await page.goto('/');

      // ナビゲーション機能
      await page.click('[data-testid="nav-products"]');
      await expect(page).toHaveURL(/.*products/);

      // 検索機能
      await page.fill(
        '[data-testid="search-input"]',
        'テスト商品'
      );
      await page.press(
        '[data-testid="search-input"]',
        'Enter'
      );

      // 検索結果の確認
      await page.waitForSelector(
        '[data-testid="search-results"]'
      );
      const results = await page.locator(
        '[data-testid="product-item"]'
      );
      expect(await results.count()).toBeGreaterThan(0);
    });
  });
});

チーム間コミュニケーションの改善

テスト結果の共有も、MCP を活用することで大幅に改善されました。以下は、テスト結果を Slack に自動通知する例です:

typescript// テスト結果のSlack通知
import { test, expect } from '@playwright/test';

test.afterEach(async ({ page }, testInfo) => {
  // テスト結果の情報を収集
  const testResult = {
    testName: testInfo.title,
    status: testInfo.status,
    duration: testInfo.duration,
    browserName: testInfo.project.name,
    timestamp: new Date().toISOString(),
  };

  // スクリーンショットの取得(失敗時)
  if (testInfo.status !== 'passed') {
    await page.screenshot({
      path: `screenshots/${testInfo.title}-failure.png`,
      fullPage: true,
    });
  }

  // Slack通知の送信
  await sendSlackNotification(testResult);
});

async function sendSlackNotification(testResult: any) {
  const webhook_url = process.env.SLACK_WEBHOOK_URL;
  if (!webhook_url) return;

  const message = {
    text: `テスト結果: ${testResult.testName}`,
    attachments: [
      {
        color:
          testResult.status === 'passed'
            ? 'good'
            : 'danger',
        fields: [
          {
            title: 'ステータス',
            value: testResult.status,
            short: true,
          },
          {
            title: 'ブラウザ',
            value: testResult.browserName,
            short: true,
          },
          {
            title: '実行時間',
            value: `${testResult.duration}ms`,
            short: true,
          },
        ],
      },
    ],
  };

  await fetch(webhook_url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(message),
  });
}

導入・実装のポイント

環境構築の手順

Playwright MCP の導入は、以下の手順で進めることをお勧めします:

1. 基本環境の構築

bash# プロジェクトの初期化
yarn init -y

# Playwrightのインストール
yarn add -D @playwright/test

# ブラウザの自動インストール
npx playwright install

2. MCP 関連の設定

typescript// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  testDir: './tests',
  timeout: 30000,
  expect: {
    timeout: 5000,
  },
  use: {
    baseURL: 'http://localhost:3000',
    headless: true,
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
    trace: 'on-first-retry',
  },
  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
  ],
});

3. MCP サーバーの設定

typescript// mcp-server.ts
import { MCPServer } from '@mcp/server';
import { PlaywrightTool } from './playwright-tool';

class PlaywrightMCPServer extends MCPServer {
  constructor() {
    super({
      name: 'playwright-mcp',
      version: '1.0.0',
    });

    this.addTool(new PlaywrightTool());
  }

  async initialize() {
    console.log('Playwright MCP Server initialized');
  }
}

export default PlaywrightMCPServer;

設定のベストプラクティス

現場での経験から、以下のベストプラクティスをお勧めします:

環境別設定の分離

typescript// config/environments.ts
export const environments = {
  development: {
    baseURL: 'http://localhost:3000',
    timeout: 10000,
    headless: false,
  },
  staging: {
    baseURL: 'https://staging.example.com',
    timeout: 30000,
    headless: true,
  },
  production: {
    baseURL: 'https://www.example.com',
    timeout: 60000,
    headless: true,
  },
};

// 環境に応じた設定の読み込み
const env = process.env.NODE_ENV || 'development';
export const currentConfig = environments[env];

共通関数の活用

typescript// utils/common-actions.ts
export class CommonActions {
  static async login(
    page: any,
    username: string,
    password: string
  ) {
    await page.goto('/login');
    await page.fill('[data-testid="username"]', username);
    await page.fill('[data-testid="password"]', password);
    await page.click('[data-testid="login-button"]');

    // ログイン完了の確認
    await page.waitForSelector('[data-testid="dashboard"]');
  }

  static async logout(page: any) {
    await page.click('[data-testid="user-menu"]');
    await page.click('[data-testid="logout-button"]');
    await page.waitForSelector(
      '[data-testid="login-form"]'
    );
  }
}

効果測定と改善

業務効率化の定量評価

実際の現場での効果を測定した結果、以下のような改善が確認できました:

項目導入前導入後改善率
回帰テスト実行時間4 時間30 分87.5%
バグ発見までの時間2 日2 時間95.8%
テストカバレッジ60%90%50%
手動テスト工数20 時間/週5 時間/週75%

測定方法の具体例

typescript// テスト実行時間の測定
test.describe('パフォーマンス測定', () => {
  test('ページ読み込み時間の測定', async ({ page }) => {
    const startTime = Date.now();

    await page.goto('/');
    await page.waitForLoadState('networkidle');

    const endTime = Date.now();
    const loadTime = endTime - startTime;

    console.log(`ページ読み込み時間: ${loadTime}ms`);
    expect(loadTime).toBeLessThan(3000); // 3秒以内
  });
});

継続的な改善サイクル

効果を持続させるために、以下の改善サイクルを確立しました:

1. 週次レビュー

typescript// テスト結果の週次集計
class TestReporter {
  static generateWeeklyReport() {
    const report = {
      totalTests: 0,
      passedTests: 0,
      failedTests: 0,
      averageExecutionTime: 0,
      topErrors: [],
    };

    // レポートの生成ロジック
    return report;
  }
}

2. 失敗パターンの分析

typescript// よくある失敗パターンの分析
test('失敗パターン分析', async ({ page }) => {
  try {
    await page.goto('/complex-page');

    // 複雑な処理のテスト
    await page.click('#dynamic-button');
    await page.waitForSelector('.result', {
      timeout: 5000,
    });
  } catch (error) {
    if (error.message.includes('Target closed')) {
      // Error Code: E001
      console.error('E001: ページが予期せず閉じられました');
      console.error(
        '対処法: ページの安定性を確認してください'
      );
    } else if (
      error.message.includes('Timeout 5000ms exceeded')
    ) {
      // Error Code: E002
      console.error('E002: 要素の読み込みタイムアウト');
      console.error(
        '対処法: 待機時間を延長するか、要素セレクターを確認してください'
      );
    }
    throw error;
  }
});

3. 継続的なスクリプト改善

typescript// スクリプトの自動改善
class ScriptOptimizer {
  static async optimizeWaitTimes(page: any) {
    // 実際の読み込み時間を測定
    const startTime = Date.now();
    await page.waitForLoadState('networkidle');
    const actualLoadTime = Date.now() - startTime;

    // 最適な待機時間を算出
    const optimizedTimeout = Math.max(
      actualLoadTime * 1.5,
      1000
    );

    console.log(`推奨タイムアウト: ${optimizedTimeout}ms`);
    return optimizedTimeout;
  }
}

まとめ

導入効果の振り返り

Playwright MCP の導入により、私たちの開発現場では劇的な変化が起こりました。

技術的な効果

  • テスト自動化率の向上: 60% → 90%
  • バグ発見効率の改善: 従来比 95.8%短縮
  • 開発サイクルの高速化: リリース頻度が 2 倍に向上

チームへの影響 もっとも印象的だったのは、チームメンバーの働き方の変化です。深夜まで手動テストを行っていたメンバーが、定時で帰宅できるようになりました。また、テストの品質が向上したことで、本番環境でのバグ発生が大幅に減少し、顧客満足度も向上しています。

学習された教訓 導入過程で学んだ最も重要なことは、「完璧を求めすぎない」ことです。最初は簡単なテストから始め、徐々に複雑なシナリオに拡張していくアプローチが成功の鍵でした。

今後の展望

Playwright MCP の可能性は、まだ始まったばかりです。

AI 連携の進化 MCP の標準化により、AI との連携がさらに深化することが予想されます。自然言語でテストシナリオを記述し、AI が自動的にテストコードを生成する時代が間近に迫っています。

クロスプラットフォーム対応 Web アプリケーションだけでなく、モバイルアプリケーションやデスクトップアプリケーションとの統合も期待されます。一つのテストツールで、すべてのプラットフォームをカバーできる未来が見えてきています。

チーム文化の変革 テスト自動化により生まれた時間を、より創造的な活動に充てることができるようになります。バグ修正に追われる日々から、新機能の開発や品質向上に集中できる環境が整いつつあります。

現場で働く皆様にとって、Playwright MCP は単なるツールではなく、より良い働き方を実現するためのパートナーとなることでしょう。一歩ずつ、着実に取り組んでいけば、必ず大きな成果を得られるはずです。

皆様の開発現場でも、この記事でご紹介した事例を参考に、業務効率化に取り組んでいただければ幸いです。技術の進歩とともに、私たちの働き方も進化していくことを、心から楽しみにしています。

関連リンク