AIエージェントが自分で直して再実行する〜Claude Code × Playwrightで作るE2Eテスト自走環境〜

テスト仕様ワークフロー図:仕様書出力からコード生成・テスト実行・結果報告までの流れを示す。

こんにちは。サイオステクノロジー武井です。

PlaywrightによるE2Eテストをできる限り自動化するためのエージェントとスキルを作りました。前提となるE2Eテストの説明から、実際に作ったエージェントの構成までを順に紹介します。

E2Eテストとはそもそも何か

E2Eテストは、画面操作を伴うテストを自動で行うもの、つまりブラウザ操作を自動化する仕組みです。代表的なOSSが Playwright で、Microsoftが開発しています。以前は Selenium が広く使われていましたが、現在は Playwright が主流になっています。

テストの自動化という点では、ユニットテストにも自動化の手段があり、PythonならPytest、JavaならJUnitが使われます。今回扱うのはそれとは別で、ブラウザ画面の操作を伴うテストを自動化するものです。

Playwright は現在、事実上E2Eテストのデファクトスタンダードと言える位置にあります。

E2Eがカバーする範囲

先ほどテストの自動化のツールにはさまざなまなものがあると説明しましたが、E2Eテストがカバーする範囲を明確にしてみます。

E2Eテストがカバーする範囲は上図の通り、要件定義の機能要件と、基本設計の画面とコンポーネントの接続部分です。逆に、非機能要件や、画面が絡まないコンポーネント同士の結合テストはE2Eテストの対象外になります。これは当然と言えば当然で、E2Eテストはあくまで画面操作を伴うテストの自動化であり、画面が絡まない部分はそもそもE2Eの対象外だからです。

本記事の対象外とはなりますが、ユニットテストやAPIテストなど、画面操作を伴わないテストの自動化には、PytestやJUnitなどが使われます。これらはE2Eテストとは別の領域であり、今回のエージェントでは扱いません。これらは基本設計内にある画面が絡まないコンポーネント同士の結合テストや、詳細設計に定義されているコンポーネントの単体テストで使われることが多いです。

今回作ったもの ─ 3つのエージェント

今回作ったエージェントは上図のような構成で、以下のGitリポジトリから取得できます。

https://github.com/noriyukitakei/e2e-automation-agents

エージェントは、次の3つに分かれています。

  1. testspec-writer(テスト仕様書を起こす)
  2. testspec-to-code(仕様書からPlaywrightコードを生成する)
  3. test-runner(実行して結果を切り分ける)

この3つは責務を完全に分離しています。

まずはtestspec-writerエージェントです。これは設計書を読んでテスト仕様書を起こします。

次に testspec-to-code エージェントは、testspec-writer が作成したテスト仕様書をもとに、Playwrightのテストコードを生成します。

最後に、test-runner エージェントです。これは生成されたテストコードを実行し、結果を切り分ける役割を持ちます。

キモとしては、この3つのエージェントがフィードバックループを形成している点にあります。コードを生成して実行し、失敗したら原因を切り分けて、コード側の問題ならコード生成に差し戻す、という流れです。

先の図に基づいてテストを実行するまでのプロセスを説明します。

① テスト仕様書を出力

testspec-writer エージェントが設計書を読み込み、テスト仕様書を起こします。出力先は docs/testspec/{機能名}.md というファイルです。

テスト仕様書は、testspec-formatスキルに基づき、以下の書式で出力されます。

内容
ケースIDTC-001 等。テストコードとの対応キー
分類正常系 / 異常系 / 境界値
テスト内容何を確かめるか(人間可読)
事前条件テスト開始前の状態
操作手順①②③ の番号付きの人間の動作
期待結果何が画面に起きるべきか(具体的に)
要件ID由来する設計要件(追跡用)

サンプルは以下のとおりとなります。

ケースID分類テスト内容事前条件操作手順期待結果要件ID
TC-001正常系正しい情報でログイン未ログイン①ログイン画面を開く ②メールとパスワードを入力 ③ログインを押すダッシュボードに遷移し、ユーザー名が表示されるREQ-12

② テスト仕様書の読み込み

testspec-to-code エージェントが、①で出力されたテスト仕様書を読み込みます。

③ MCPに接続

続いて testspec-to-code エージェントが Playwright MCP サーバーに接続します。Playwright MCP は、指定したWeb画面にアクセスして画面のさまざまな情報を取得できるツールです。

④ DOMの読み込み

Playwright MCP がテスト対象のWeb画面にアクセスし、そのDOM情報を読み込みます。これにより実際のセレクター(role / label / testid)を取得でき、テストコードを生成する際に実画面とのズレが起きないようにします。

⑤ テストコードの生成・修正

testspec-to-code エージェントが、Playwright MCP から取得したセレクター情報とテスト仕様書の内容をもとに、テストコードを生成します。出力先は tests/e2e/{機能名}.spec.ts です。

⑥ テストコードの読み込み

test-runner エージェントが、⑤で生成されたテストコードを読み込みます。

⑦ テスト実行

test-runner エージェントが、読み込んだテストコードをもとにテスト対象のWeb画面に対してテストを実行します。

テストが成功すればそのままで問題ありませんが、失敗した場合は原因を次の4つに分類します。

  • A:セレクターのズレ。たとえばコードが getByTestId を使っている場合、既定では data-testid を探しに行きますが、実際のDOMには data-test と書かれている、というケースです。画面自体は正常なのに要素が見つからず、タイムアウトしてしまいます。
  • B:タイミング待ち不足。テストの待ち方の問題です。ログイン直後など、まだ描画が完了していない段階でアサーションを評価してしまい、タイムアウトする場合がこれにあたります。
  • C:実装側のバグ。アプリ本体、つまり仕様と挙動の不一致です。仕様書には合計 $43.18 と書かれているのに、実画面では $40.00 が表示されている、といったケースで、これは単なるバグです。
  • D:環境・データ起因。サイト障害で接続できない、といった環境側の問題です。

分類に応じて、その後の処理が変わります。AとBはコード側の問題なので、testspec-to-code へ差し戻します。たとえばAはセレクターの指定ミスなので、生成役にその箇所を修正させます。

一方でCとDは、コードを直しても解決しません。アプリ自体の不具合や環境起因の問題であり、testspec-to-code では対応のしようがないため、人間に通知して停止します。

分類何が原因か差し戻し先
Aセレクターのズレ(コード側)testspec-to-code
Bタイミング待ち不足(コード側)testspec-to-code
C実装側のバグ(仕様と挙動の不一致)人間
D環境・データ起因人間

このtestspec-to-codetest-runnerのフィードバックループの上限回数は3回に設定しています。3回コードを修正してもテストが通らない場合は、コード側の問題ではない可能性が高いので、人間に通知して停止します。

⑧ 差し戻し

実行結果の失敗原因がA(セレクタずれ)またはB(タイミング待ち不足)だった場合は、testspec-to-code エージェントに差し戻され、Playwright コードを修正します。以降は②〜⑦と同じ流れを繰り返します。この差し戻しループは最大3回までで、3周しても失敗が続く場合(C:実装バグ疑い/D:環境・データ起因)は人間にエスカレーションします。

やってみよう

とは言いつつも、実際にやる手順は Claude Code を起動して「docs/design にある設計書をもとに、E2Eテストを実行して」と指示するだけです。あとはエージェントが自動で動いてくれます。必要なモジュールがなければ、それも自動でインストールしてくれます。

E2Eテストでよく使われる Sauce Demo(https://www.saucedemo.com/)を例に、実際にやってみましょう。

先ほど紹介したソースコードのディレクトリには、この Sauce Demo を題材にした設計書がすでに入っています。パスは docs/design/saucedemo.md です。これをもとに E2Eテストを実行してみます。

以下を Claude Code のプロンプトにコピペしてみてください。

saucedemoのE2Eテストを実行して。仕様書はdocs/design/saucedemo.mdにあるよ。

すると、必要なモジュールなどがなければ自動でインストールされます。

あとはエージェントにお任せです。テストコードの生成から実行、失敗した場合の原因の切り分けと差し戻しまで、すべて自動でやってくれます。

テストコードは tests/e2e/saucedemo.spec.ts に保存されます。

エビデンスは tests/evidence フォルダに保存されます。Playwright がテスト実行時にスクリーンショットを撮って残してくれます。

レポートは2種類出力されます。ひとつは HTML レポートで、tests/playwright-report/ に保存されます(npx playwright show-report tests/playwright-report で開けます)。もうひとつは CI やテスト管理ツールへの取り込み用の JUnit XML で、tests/test-results/junit.xml に保存されます。

実行結果は以下のようになりました

テストコードの生成と実行、つまりtestspec-to-code と test-runnerのフィードバックループが3周しているのがわかりますでしょうか?

例えば、1周目は、セレクターのズレです。テストコードが getByTestId を使っているのに、実際のDOMには data-test と書かれていました。getByTestIdが期待するのは data-testid なので、画面自体は正常なのに要素が見つからずタイムアウトしてしまいました。これが分類Aのセレクターのズレにあたります。これはAに分類されてるので、コード側の問題として testspec-to-codeに差し戻され、コードを修正してもらっています。

その後修正と実行を繰り返し、最終的にはCの実装バグ疑いで人間にエスカレーションされました。実際、テストコードの問題ではなく、アプリ側の不具合だったため、コードを修正してもテストが通らず、3周しても解決しなかったため、人間に通知されて停止しました。

ここで見た通り、テストコードの生成と実行のフィードバックループが自動で回ることで、セレクターのズレやタイミング待ち不足といったコード側の問題は自動で修正され、実装バグや環境起因の問題は人間に通知してエスカレーションする、という流れができています。

おわりに

今回は、テスト仕様書の作成からコード生成、テスト実行、失敗した場合の原因切り分けと差し戻しまでを自動で回す E2E エージェントを紹介しました。

これを使ってE2Eテストを自動化して、ベルサッサしてハナキンをエンジョイしましょう。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。
エンジニア募集中!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です