1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIでPlaywrightのテストシナリオ作成

Last updated at Posted at 2025-08-18

前回からの続き

前回は、Playwrightを使って自動テストを試してみました。

自動テストとても便利なツールと思いつつも、テストシナリオ作成する作業、それも特に最初の1つを作るのって、結構大変です。
Playwrightにレコーディング機能があるとは言え、ポチポチ操作しつつ、なんとなく気に入らない場所を修正したりと、それなりに手間がかかります。

そこで、今回は、AIを使って対象のページから自動でテストシナリオを作ってもらいます。

Playwright MCP

AIを積極的に使用し、使えるものは使う。仕事の効率化を図るというのはとても大事なことだと思います。

そこで以下の文章をGithub Copilotで記述してみました。

http://localhost:8080/testapp/users/addを確認して、Playwright用のテストシナリオを提案してください。

しかし私の作ったユーザー追加ページを知っている訳もなく、基本的なシナリオ例として、全然違う架空のユーザー追加ページのテストシナリオを作り出してくれます。

import { test, expect } from '@playwright/test';

test('ユーザー追加画面の基本動作', async ({ page }) => {
  await page.goto('http://localhost:8080/testapp/users/add');

  // ページタイトル確認
  await expect(page).toHaveTitle(/ユーザー追加|User Add/);

  // 必須項目未入力で送信
  await page.click('button[type="submit"]');
  await expect(page.locator('.error-message')).toBeVisible();

  // 正しい情報を入力して送信
  await page.fill('input[name="username"]', 'testuser');
  await page.fill('input[name="email"]', 'test@example.com');
  await page.fill('input[name="password"]', 'password123');
  await page.click('button[type="submit"]');

  // 成功メッセージまたはリダイレクト確認
  await expect(page).toHaveURL(/users/);
  await expect(page.locator('.success-message')).toBeVisible();
});

そこで、Playwright MCPです。
MCPプロトコル(Pがすでにプロトコル?)を使って、ローカルの資源にバンバンアクセスしてもらいます。
VS CodeのGithub Copilotを、"Agent"モードに設定。
更にMCPサーバーで、playwright を有効にしておきます。

MCP有効に.png

その上であらためて...

実際に、http://localhost:8080/testapp/users/addの内容をアクセスして確認した上でPlaywrightのテストシナリオを作成してください。

何が引き金で、MCP経由でローカル資源にアクセスしてくれるのか、正直まだつかみ切れていない部分もあるのですが、今回はこんな感じのしつこい文章で、MCP経由でブラウザを起動。
実際に指定したページの内容に沿ったテストシナリオを作成してくれました。

import { test, expect } from '@playwright/test';

test('ユーザー追加画面のバリデーションと登録', async ({ page }) => {
  await page.goto('http://localhost:8080/testapp/users/add');

  // ページタイトル確認
  await expect(page).toHaveTitle(/CakePHP:.*Users/);

  // 必須項目未入力で送信
  await page.click('button:has-text("Submit")');
  // エラー表示の有無はCakePHPの実装に依存(必要に応じて追加)

  // 正しい情報で登録
  await page.fill('input[aria-label="Name"]', 'テスト太郎');
  await page.fill('input[aria-label="Email"]', 'test@example.com');
  await page.fill('input[aria-label="Password"]', 'password123');
  await page.selectOption('select[aria-label="Sex"]', { label: 'male' });

  // 登録後の遷移やメッセージを確認(例: 一覧画面への遷移)
  await expect(page).toHaveURL(/\/users/);
});

Playwrightで作成したシナリオを実行

早速、AIが作ったシナリオを実行してみます。
結果は...

ADDできちゃった.png

NGです。理由は、このユーザー追加ページのバリデーションが正しく設定されておらず、
空白のままユーザーが追加できてしまうという残念な状況でした。

ある意味、AIが作ったテストシナリオによって、バグが見つかったという事です。
(残念過ぎるバグですが...)

ソースを修正し、必須入力となるべくバリデーションチェックを設定します。

class UsersTable extends Table
{
       :
    public function validationDefault(Validator $validator): Validator
    {
-        $validator
-            ->scalar('name')
-            ->maxLength('name', 32)
-            ->allowEmptyString('name');
-        $validator
-            ->email('email')
-            ->allowEmptyString('email');
+        $validator
+            ->scalar('name')
+            ->maxLength('name', 32)
+            ->notEmptyString('name');
+        $validator
+            ->scalar('email')
+            ->maxLength('email', 64)
+            ->notEmptyString('email');
+        $validator
+            ->scalar('password')
+            ->maxLength('password', 32)
+            ->notEmptyString('password');
        return $validator;
    }
        :

そして再度テスト実行。
今度は成功...と言いたいところですが、まだ上手くいきません。
そもそもAIによって作成されたシナリオが上手く動作しないようで、一部手直ししました。

  // 正しい情報で登録
-  await page.fill('input[aria-label="Name"]', 'テスト太郎');
-  await page.fill('input[aria-label="Email"]', 'test@example.com');
-  await page.fill('input[aria-label="Password"]', 'password123');
-  await page.selectOption('select[aria-label="Sex"]', { label: 'male' });
+  await page.getByRole('textbox', { name: 'Name' }).fill('テスト太郎');
+  await page.getByRole('textbox', { name: 'Email' }).fill('test@example.com');
+  await page.getByRole('textbox', { name: 'Password' }).fill('password123')
+  await page.getByLabel('Sex').selectOption({ label: 'male' });

ロケータ関係が上手くいってないようで、前回のシナリオを参考に変更しています。
ただ、この部分こそ、AIで自動で生成して欲しい部分ではあるのですが...

そして今度こそ。

ADDできちゃったのなおした.png

無事テストシナリオが最後まで動作しました。

最後に

私の使い方。指示の仕方に問題があるのかもしれませんが、どうにも上手くシナリオを作ってもらうことができません。
惜しいところまではと思うのですが、まだまだ試行錯誤の時間が長すぎて、これなら自分でレコーディング機能つかいつつシナリオ作った方が早いっていう状況です。

更に言うと、ローカルLLMで一切クラウドに情報を出さす、シナリオをバンバンAIに作って欲しいとも思うのですが、それこそ、ああでもない、こうでもないと...またローカルなLLMはへそ曲げるとすぐに英語で話し出す。
PCはどんどん熱を発し、時間ばかり消費し、いまだ期待した結果を得ることができずにいます。

この辺りは、今後も地道にトライしていこうと思う今日この頃です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?