はじめに:自動テストが吐く「嘘」
Webフロントエンドの開発において、PlaywrightやCypressを用いたE2Eテストはもはや標準です。しかし、現場で運用していると、必ず以下のような「自動テストの限界」にぶつかります。
// ❌ このテストはPASSするが、人間にはクリックできない可能性がある
await expect(page.locator('#submit-button')).toBeVisible();
await page.locator('#submit-button').click();
現場の絶望(すり抜けるバグ)
DOM上には確かにボタンが存在し、display: none でもないためテストはPASSします。しかし本番環境では、「ボタンの上に絶対配置(absolute)されたバナーが被さっていて、人間には物理的にクリック不可能だった」 という事態が頻発します。
CSSの z-index や画面幅によるレイアウト崩れによって「視覚的」には機能不全に陥っている状態。これを防ぐために、結局リリース前にディレクターが目視でポチポチ確認する「人海戦術」に戻っていないでしょうか?
本記事では、Playwrightの自動化能力と最新のVision LLM(画像認識AI)を組み合わせ、「DOMではなく人間の目のように『見た目』を検証する」自律型VRT(Visual Regression Testing)エージェントのアーキテクチャを解説します。
アーキテクチャ:Playwright × Vision LLM
従来のVRT(ピクセルマッチング)は、OSのフォントレンダリングの違いや、1pxのズレでテストが落ちる「フレーキー(不安定)なテスト」になりがちでした。
そこで、**「スクリーンショットを撮り、AIに『UIとして破綻していないか』を判断させる」**アプローチを取ります。
実装コンセプト(TypeScript)
コアとなる検証ロジックの概念コードです。AIの出力を安定させるため、Structured Outputs(構造化出力)を要求します。
import { test, expect } from '@playwright/test';
import { GoogleGenerativeAI } from '@google/generative-ai';
// APIキーの初期化
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY!);
test('スマホ幅でCTAボタンが他の要素と被っていないか視覚検証', async ({ page }) => {
// 1. ページ遷移とスマホ幅設定
await page.setViewportSize({ width: 375, height: 812 });
await page.goto('[https://example.com/lp](https://example.com/lp)');
// 2. スクリーンショットの取得
const screenshotBuffer = await page.screenshot();
const base64Image = screenshotBuffer.toString('base64');
// 3. Vision LLMへの検証依頼
const model = genAI.getGenerativeModel({ model: "gemini-3.1-pro" });
const prompt = `
あなたはプロのQAエンジニアです。
添付されたWebページのスクリーンショットを見て、以下の点を検証し、JSONのみで回答してください。
【検証項目】
- "今すぐ申し込む"ボタンがテキストや他の要素と重なっていませんか?
- ユーザーが視覚的に問題なくクリックできる状態ですか?
【出力フォーマット】
{ "isPass": boolean, "reason": "理由の詳細" }
`;
const result = await model.generateContent([
prompt,
{ inlineData: { data: base64Image, mimeType: "image/png" } }
]);
// 4. 結果のパースとアサーション
const responseText = result.response.text().replace(/```json|```/g, '').trim();
const aiResponse = JSON.parse(responseText);
console.log(`AI判定理由: ${aiResponse.reason}`);
// AIが視覚的な問題を発見した場合はテストを落とす
expect(aiResponse.isPass, `視覚的エラー: ${aiResponse.reason}`).toBe(true);
});
エッジケースの突破:ステートフルな検証
このアーキテクチャの強力な点は、「カートに商品を入れた後、決済画面から『戻る』を押した時の表示崩れ」といった、複雑なステート(状態)を持った画面の視覚検証が容易になることです。
Playwrightに複雑なシナリオを走らせ、要所要所で page.screenshot() を撮り、AIに検証させる。これにより、「DOMの変更には強いが、視覚的な崩れには弱い」という従来のE2Eテストの弱点を完全に克服できます。
コストと実行速度についての考察
AIを利用したテストはAPIのレイテンシとコスト(1回数円)が発生するため、数千のテストケースを毎回回すのには向きません。重要なCTAや、レイアウトが壊れやすい主要な導線に絞って「要所要所の目視チェック」を代行させるのが実用的です。
課題と運用環境(隔離サンドボックス)
開発途中のプレビューURLや社内環境を外部API(LLM)に送信する際は、機密情報のマスキングやセキュリティの考慮が必須です。
現在私は、これらのエージェントをクラウド上ではなく、ネットワークが隔離された 物理エッジサーバー(ローカルのMac mini等) 上でn8n等のワークフローエンジンと連携させ、深夜にバッチ処理として実行する「Shadow DevOps」環境を構築して運用しています。
まとめ
E2Eテストは「要素がDOMに存在するか」から、AIの目を使った「ユーザーに正しく見えているか」のフェーズへ移行しつつあります。
「テストコードの保守」より「AIにどう見させるか(プロンプトとアーキテクチャ設計)」に頭を使う方が、結果としてROIの高い品質保証システムが構築できるはずです。
著者:
@YushiYamamoto
株式会社プロドウガ CEO / AIアーキテクト
Next.js / TypeScript / Playwrightを活用した自律型テスト・アーキテクチャ設計を専門としています。
日々の自動化の検証結果や、ビジネス側の視点(ROI等)に関するより深い考察は、以下の公式サイトおよびnoteで発信しています。