← ブログ一覧に戻る
業務自動化

Cursor/Claude CodeでPlaywright RPAを開発する効率的なワークフロー

#Cursor#Claude Code#Playwright#RPA#コーディングエージェント#TypeScript

はじめに

Playwrightを使ったRPA開発は、手動でコードを書くと時間がかかります。特に、UI操作の待機処理、エラーハンドリング、テストコードの作成など、細かい実装が多く、開発速度に影響します。

CursorClaude Codeなどのコーディングエージェントを活用することで、Playwright RPAの開発を大幅に効率化できます。この記事では、実際のプロジェクトで活用した経験を基に、効率的な開発ワークフローを解説します。

コーディングエージェントでPlaywright RPAを開発するメリット

1. コード生成の高速化

UI操作のコードを自然言語で指示するだけで、適切なPlaywrightコードが生成されます。

2. エラーハンドリングの自動生成

よくあるエラー(要素が見つからない、タイムアウトなど)に対する処理を自動で提案してくれます。

3. テストコードの生成

RPAの動作を検証するテストコードも、エージェントが生成してくれます。

実践例1:基本的なRPAコードの生成

プロンプト設計

効果的なプロンプトの例:

PlaywrightでRPAコードを作成してください。

要件:
- 対象URL: https://example.com/admin
- 操作フロー:
  1. ログインページにアクセス
  2. メールアドレスとパスワードを入力
  3. ログインボタンをクリック
  4. ダッシュボードが表示されるまで待機
  5. 売上レポートページに移動
  6. CSVダウンロードボタンをクリック
  7. ダウンロード完了を待機

- エラーハンドリング: 各ステップで要素が見つからない場合はログ出力して終了
- 待機時間: 各操作後に適切な待機を設定

生成されたコード例

import { chromium, Page } from '@playwright/test';
import * as fs from 'fs';

async function login(page: Page, email: string, password: string): Promise<void> {
  await page.goto('https://example.com/admin/login');
  
  await page.getByLabel('メールアドレス').fill(email);
  await page.getByLabel('パスワード').fill(password);
  await page.getByRole('button', { name: 'ログイン' }).click();
  
  // ダッシュボードが表示されるまで待機
  await page.waitForSelector('[data-testid="dashboard"]', { timeout: 10000 });
}

async function downloadSalesReport(page: Page): Promise<string> {
  // 売上レポートページに移動
  await page.getByRole('link', { name: '売上レポート' }).click();
  await page.waitForURL('**/sales-report');
  
  // CSVダウンロード
  const [download] = await Promise.all([
    page.waitForEvent('download'),
    page.getByRole('button', { name: 'CSVダウンロード' }).click(),
  ]);
  
  const path = await download.path();
  if (!path) {
    throw new Error('ダウンロードに失敗しました');
  }
  
  return path;
}

async function runRPA() {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  
  try {
    await login(page, process.env.EMAIL!, process.env.PASSWORD!);
    const csvPath = await downloadSalesReport(page);
    console.log(`CSV downloaded: ${csvPath}`);
  } catch (error) {
    console.error('RPA実行エラー:', error);
    await page.screenshot({ path: 'error-screenshot.png' });
    throw error;
  } finally {
    await browser.close();
  }
}

実践例2:エラーハンドリングの改善

エージェントに既存のコードとエラー情報を提示すると、改善案を提案してくれます。

改善前のコード

async function clickButton(page: Page, buttonText: string) {
  await page.getByRole('button', { name: buttonText }).click();
}

問題点:

  • ボタンが見つからない場合の処理がない
  • タイムアウトの設定がない
  • エラーログがない

エージェントへの指示

この関数を改善してください。

要件:
- 要素が見つからない場合はエラーログを出力して終了
- タイムアウトは10秒に設定
- スクリーンショットを保存
- エラー情報を詳細に記録

改善後のコード

async function clickButton(
  page: Page, 
  buttonText: string, 
  timeout: number = 10000
): Promise<void> {
  try {
    const button = page.getByRole('button', { name: buttonText });
    await button.waitFor({ state: 'visible', timeout });
    await button.click();
  } catch (error) {
    const screenshotPath = `error-${Date.now()}.png`;
    await page.screenshot({ path: screenshotPath, fullPage: true });
    
    console.error(`ボタンクリック失敗: ${buttonText}`, {
      error: error instanceof Error ? error.message : String(error),
      screenshot: screenshotPath,
      url: page.url(),
    });
    
    throw new Error(`ボタン "${buttonText}" のクリックに失敗しました: ${error}`);
  }
}

実践例3:テストコードの自動生成

RPAの動作を検証するテストコードも、エージェントが生成してくれます。

エージェントへの指示

このRPAコードのテストコードを作成してください。

要件:
- ログイン処理のテスト
- CSVダウンロード処理のテスト
- エラーケースのテスト(不正な認証情報など)
- モックを使ったテストも含める

使用ライブラリ: @playwright/test

生成されたテストコード例

import { test, expect } from '@playwright/test';
import { login, downloadSalesReport } from './rpa';

test.describe('RPA Tests', () => {
  test('正常系: ログインとCSVダウンロード', async ({ page }) => {
    // ログイン
    await login(page, '[email protected]', 'password123');
    
    // ダッシュボードが表示されていることを確認
    await expect(page.getByTestId('dashboard')).toBeVisible();
    
    // CSVダウンロード
    const csvPath = await downloadSalesReport(page);
    
    // ファイルがダウンロードされたことを確認
    expect(csvPath).toBeTruthy();
    const fs = require('fs');
    expect(fs.existsSync(csvPath)).toBe(true);
  });
  
  test('異常系: 不正な認証情報でログイン失敗', async ({ page }) => {
    await page.goto('https://example.com/admin/login');
    
    await page.getByLabel('メールアドレス').fill('[email protected]');
    await page.getByLabel('パスワード').fill('wrongpassword');
    await page.getByRole('button', { name: 'ログイン' }).click();
    
    // エラーメッセージが表示されることを確認
    await expect(page.getByText('ログインに失敗しました')).toBeVisible();
  });
  
  test('異常系: 要素が見つからない場合', async ({ page }) => {
    await page.goto('https://example.com/admin');
    
    // 存在しないボタンをクリックしようとする
    const button = page.getByRole('button', { name: '存在しないボタン' });
    
    await expect(button).toBeVisible({ timeout: 1000 }).catch(() => {
      // タイムアウトが発生することを確認
    });
  });
});

実践例4:リファクタリング支援

既存のRPAコードを、エージェントの支援でリファクタリングする例です。

リファクタリング前

// 重複が多いコード
async function runJobA() {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  try {
    await page.goto('https://site-a.com/login');
    await page.fill('#email', '[email protected]');
    await page.fill('#password', 'pass123');
    await page.click('button[type="submit"]');
    await page.waitForSelector('.dashboard');
    // ...
  } finally {
    await browser.close();
  }
}

async function runJobB() {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  try {
    await page.goto('https://site-b.com/login');
    await page.fill('#email', '[email protected]');
    await page.fill('#password', 'pass123');
    await page.click('button[type="submit"]');
    await page.waitForSelector('.dashboard');
    // ...
  } finally {
    await browser.close();
  }
}

エージェントへの指示

このコードをリファクタリングしてください。

要件:
- 共通処理を関数に抽出
- 設定を外部化(環境変数や設定ファイル)
- 型安全性を向上
- エラーハンドリングを統一

リファクタリング後

interface RPAConfig {
  baseUrl: string;
  credentials: {
    email: string;
    password: string;
  };
  selectors: {
    emailInput: string;
    passwordInput: string;
    submitButton: string;
    dashboardSelector: string;
  };
}

class RPARunner {
  constructor(private config: RPAConfig) {}
  
  async login(page: Page): Promise<void> {
    await page.goto(`${this.config.baseUrl}/login`);
    await page.fill(this.config.selectors.emailInput, this.config.credentials.email);
    await page.fill(this.config.selectors.passwordInput, this.config.credentials.password);
    await page.click(this.config.selectors.submitButton);
    await page.waitForSelector(this.config.selectors.dashboardSelector);
  }
  
  async runWithBrowser<T>(
    operation: (page: Page) => Promise<T>
  ): Promise<T> {
    const browser = await chromium.launch();
    const page = await browser.newPage();
    
    try {
      return await operation(page);
    } finally {
      await browser.close();
    }
  }
}

// 使用例
const jobAConfig: RPAConfig = {
  baseUrl: 'https://site-a.com',
  credentials: {
    email: process.env.EMAIL_A!,
    password: process.env.PASSWORD_A!,
  },
  selectors: {
    emailInput: '#email',
    passwordInput: '#password',
    submitButton: 'button[type="submit"]',
    dashboardSelector: '.dashboard',
  },
};

const runner = new RPARunner(jobAConfig);
await runner.runWithBrowser(async (page) => {
  await runner.login(page);
  // その他の処理
});

効率的な開発ワークフロー

1. 要件定義からコード生成まで

1. 要件を自然言語で整理
   ↓
2. エージェントにプロンプトで指示
   ↓
3. 生成されたコードをレビュー
   ↓
4. 必要に応じて改善指示
   ↓
5. テストコードを生成
   ↓
6. 実際の環境で動作確認

2. 段階的な開発

一度にすべてを生成させるのではなく、小さな単位で段階的に開発します。

  1. 基本的なUI操作(ログインなど)
  2. メイン処理(データ取得など)
  3. エラーハンドリング
  4. ログ出力と通知
  5. テストコード

3. コードレビューのポイント

エージェントが生成したコードは、必ず以下の点を確認します。

  • セレクタの適切性: 変更に強いセレクタか
  • 待機処理: 適切な待機が設定されているか
  • エラーハンドリング: 想定外のエラーに対応できているか
  • パフォーマンス: 不要な待機がないか

注意点と制限事項

エージェントの限界

  • 最新のAPI情報: Playwrightの最新機能を理解していない場合がある
  • サイト固有の仕様: 各サイトの特殊な動作は理解できない
  • セキュリティ: 認証情報の扱いに注意が必要

必ず確認すべきこと

  1. 環境変数の管理: 認証情報は環境変数で管理
  2. エラーログ: 十分な情報が記録されているか
  3. 冪等性: 同じ処理を複数回実行しても問題ないか
  4. 監視と通知: 失敗時の通知が設定されているか

まとめ

CursorやClaude Codeなどのコーディングエージェントを活用することで、Playwright RPAの開発を大幅に効率化できます。

効果的な活用方法:

  • 具体的で構造化されたプロンプトを使用
  • 段階的に開発を進める
  • 生成されたコードを必ずレビュー
  • テストコードも自動生成

改善前:

  • RPAコードの作成に数日かかる
  • エラーハンドリングの実装が不十分
  • テストコードの作成に時間がかかる

改善後:

  • エージェントの支援で開発時間を大幅短縮
  • 堅牢なエラーハンドリングが自動生成
  • テストコードも効率的に作成

コーディングエージェントは、Playwright RPA開発の「強力なパートナー」として活用することで、より効率的で保守性の高いコードを実現できます。


関連リンク: