5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Playwright × 生成AI】DOMを信用するな。CSSの「表示崩れ」を視覚的に検知する自律型VRTエージェントの構築

5
Posted at

はじめに:自動テストが吐く「嘘」

Webフロントエンドの開発において、PlaywrightやCypressを用いたE2Eテストはもはや標準です。しかし、現場で運用していると、必ず以下のような「自動テストの限界」にぶつかります。

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(構造化出力)を要求します。

tests/vrt.spec.ts
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で発信しています。

5
6
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
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?