Playwright MCP を使って、自然言語で E2E テストを実行してみた

## はじめに

Playwright MCP を使って、自然言語から E2E テストを実行できるかどうかを試してみました。今回は、[デスクトップ版の Claude](https://claude.ai/download) を利用して、プロンプトを入力してテストを実行してみます。テスト対象のアプリケーションは、ブラウザベースで操作可能な TODO を管理するサンプルアプリを対象としました。
Playwright MCP の詳細については、公式のドキュメントを確認してください。

https://github.com/microsoft/playwright-mcp

### 実行環境

- Claude for Mac: `0.9.1`
  - Claude Pro プラン（Free プランでも制限内で、実行はできます）
- @playwright/mcp: `0.0.9`

### テスト対象のサンプルアプリについて

テストを実行するサンプルアプリケーションは TODO タスクを CRUD できるようなシンプルな WEB アプリです。以下のような機能があります。

- タスクを新規作成、編集、削除
- タスクのステータスを完了、未完了に変更できる
- 各タスクを一覧表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331769/4b77aa30-939a-4b75-b76a-0e26a88a813c.png)

サンプルアプリのリポジトリはこちらです。

https://github.com/ore88ore/react-todo-app-example

## Playwright MCP のインストール

デスクトップ版(macOS)の Claude に Playwright MCP をインストールします。MCP のインストール方法については、[Claude の公式ドキュメント](https://modelcontextprotocol.io/quickstart/user)を参考にしてください。

今回は[公式のサンプル](https://github.com/microsoft/playwright-mcp?tab=readme-ov-file#example-config)を参考に以下の設定でインストールしました。

```
/// 該当部分のみ ///
    "playwright": {
      "command": "npx",
      "args": [
        "@playwright/mcp@latest"
      ]
    }
```

引数で指定可能なオプションもいくつかあります。Playwright でおなじみのヘッドレスで実行するオプション(`--headless`)やブラウザを指定するオプション(`--browser <browser>`)なんかもありますね。必要に応じて `args` に指定することができます。

https://github.com/microsoft/playwright-mcp?tab=readme-ov-file#cli-options

設定を追加後に Claude を再起動すると、インストールできていることを確認できます。

![Monosnap Image 2025-04-02 11-08-17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331769/458f8731-1baf-4f43-adca-886bb65253ec.png)

## テストを実行

実行環境ができましたので、プロンプトを作成して、サンプルアプリに対してテストを実行してみます。なお、サンプルアプリはアクセスできるように起動しておく必要があります。

### プロンプトからテストを実行する

以下のようなプロンプトを実行して、正常系の E2E テストを実行してみました。

```text:入力プロンプト
以下のアプリに対して、正常系E2Eテストを実行してください。 
## 対象アプリ
http://localhost:5173/

## テストケース
- 新規でタスクを作成できること
- 作成済みのタスクを更新できること
- タスクを完了としてマークできること
- 完了タスクを未完了に戻せること
- タスクを削除できること

## 出力形式 
- 各ケースの結果をOK/NGで報告してください
- テスト結果がNGの場合、失敗した場合は簡潔な理由を添えてください
- すべてのテスト結果をテーブル表示で、サマリを表示してください
```

:::note
チャット内で初めてツールを実行する際、以下のような確認ダイアログが表示されることがあります。このダイアログはセキュリティのために表示されるものですので、内容を確認した上で適切な操作を選択してください。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331769/8154853c-c273-43e9-8a62-9f7e5dfe2532.png">
:::






プロンプトを実行すると、順番にテストが実行されていくことを確認できます。これくらい抽象的な指示でも意図した動きになっていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331769/1753dbe9-963c-49d3-b078-91305ca15e96.png)

各コマンドの `結果を表示` を展開すると、WEB ページの構造をどのように解析しているかも確認することができました。この解析をもとに、どこをクリックし、どこに入力するかを判定しているものと思われます。

```
{
  `ref`: `s1e21`,
  `element`: `新規タスク作成`
}
"新規タスク作成" clicked

- Page URL: http://localhost:5173/create
- Page Title: Vite + React + TS
- Page Snapshot

- banner [ref=s2e5]:
    - heading "Todo App" [level=1] [ref=s2e7]:
        - link "Todo App" [ref=s2e8]:
            - /url: /
    - navigation [ref=s2e9]:
        - list [ref=s2e10]:
            - listitem [ref=s2e11]:
                - link "ホーム" [ref=s2e12]:
                    - /url: /
            - listitem [ref=s2e13]:
                - link "新規作成" [ref=s2e14]:
                    - /url: /create
            - listitem [ref=s2e15]:
                - link "完了済み" [ref=s2e16]:
                    - /url: /completed
- main [ref=s2e17]:
    - heading "新規タスク作成" [level=2] [ref=s2e20]
    - text: タイトル
    - textbox "タイトル" [ref=s2e24]
    - text: 説明
    - textbox "説明" [ref=s2e27]
    - button "キャンセル" [ref=s2e29]
    - button "作成" [ref=s2e30]
- contentinfo [ref=s2e31]:
    - paragraph [ref=s2e33]: © 2025 Todo App Example - Playwright テスト用
```

また、今回は `headed`（デフォルト設定） で実行しているので、ブラウザも自動起動してどのような操作を実行しているかを確認することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331769/1ff3ecff-71f6-4f8b-ac77-1e1c78f4ee67.png)

### テスト結果を確認

プロンプトにてテスト結果をサマリで表示するようにしました。テスト結果は以下のようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331769/956164d6-7e74-4d1a-b2fc-668d77f97589.png)

アプリケーションが、意図した動きになっていることを確認できました。必要に応じて出力フォーマットを扱いやすいように出力すると良さそうですね。

### エラーが発生するテストを実行してみる

特定のテストケースがエラーとなるようにサンプルを更新して、再度同じテストを実行してエラー時の挙動を確認してみます。

```text:入力プロンプト
再度同じテストを実行してください。
```

エラーが発生しないテストケースは、正常系と同様にテストが実行されて成功となりました。今回はタスクを更新する際にエラーとなるようにしましたので、作成済みのタスクを更新するテストケースを見てみます。

```text:出力メッセージ
テストケース2: 作成済みのタスクを更新できること

次に、作成したタスクを編集します。「編集」リンクをクリックします。

タスクのタイトルを変更します。

次に説明を変更します。

「更新」ボタンをクリックします。

更新後も編集画面に残ったようです。ホーム画面に戻って更新が反映されているか確認しましょう。

ホーム画面をチェックしたところ、タスクの更新が反映されていないようです。もう一度編集画面に戻り、更新を試みます。

タイトルと説明を再度入力します。

更新ボタンをクリックします。

更新後も編集画面に留まるようです。キャンセルボタンを押してホーム画面に戻ります。

ホーム画面に戻りましたが、タスクの更新が反映されていないようです。もう一度試みましょう。

別の方法で編集を試みるため、もう一度タスクの詳細画面に移動します。タスクタイトルをクリックします。

タスクの更新に問題があるようですが、テストを続行します。アプリケーションの他の機能をテストします。
```

更新処理を実行したが、更新されたかを検証して、更新されていないのでリトライする。という動きになっているようでした。更新されていることを検証できなければ、`OK` とならないことを確認できました。
また、`タスクの更新に問題があるようですが、テストを続行します。` のようになっていて、一部のテストがエラーとなっても、他のテストを継続してくれました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331769/5ac19e11-ea48-48c3-b04e-dc2e75ac35ff.png)

テスト結果のサマリを確認すると、失敗したテストケースが `NG` となっていることを確認できました。失敗の事象や状況についても共有してくれていますね。

## さいごに

今回 Playwright MCP を使ってみて、WEB アプリケーションを簡単に操作できることがわかりました。今回のようにテスト目的で使う場合は、デザインや画面の更新に伴う、テストコードの更新コストがほとんどなくなるのでは？と思えるほど、インパクトがある使い方になるのでは？と感じました。（この手の E2E テストは新規で作成するというより、変更の頻度が高い部分なので、メンテナンスしていくのが大変だと思う）
テスト以外の目的でも柔軟に使えると思うので、引き続きいろいろな使い方を試してみようと思います。
比較的簡単に使い始めることができるので、ぜひ試してみてはいかがでしょうか。