TL;DR
AIの幻覚を4つのステップで止める:(1) Playwrightをインストールし、ブレークポイント(デスクトップ、タブレット、モバイル)を設定する、(2) フルページ、レスポンシブレイアウト、インタラクションをキャプチャするスクリーンショットテストスイートを作成する、(3) 証拠を収集するために ./qa-playwright-capture.sh を実行する、(4) Reality Checkerエージェントを起動し、主張をgrep結果とスクリーンショットと照合する。エージェントは特定のブロックする問題とともにPASSまたはNEEDS WORKを出力し、もはや幻想的な承認は行われません。
はじめに
AIエージェントからの「素晴らしいですね」という言葉を受け入れるのはやめましょう。承認前に視覚的な証拠を必要とする、Playwrightのスクリーンショットを用いた証拠に基づくQAワークフローを構築しましょう。
あなたがAIエージェントにランディングページのレビューを依頼すると、次のように返答します。
The design looks premium and polished. The glassmorphism effects are well-implemented. The page is fully responsive. Ready for production!
あなたがページを開くと、「グラスモーフィズム」は単なる灰色の背景でした。「完全にレスポンシブ」なレイアウトはモバイルで崩れていました。プレミアム感も洗練さも何もありません。
AIエージェントは幻覚を見ます。彼らはあなたが聞きたいことを言います。彼らは対立を避け、すべてを承認します。
The AgencyコレクションのReality Checkerエージェントは異なるアプローチを取ります。
Status: NEEDS WORK
Evidence:
- grep for "glassmorphism" returned NO PREMIUM FEATURES FOUND
- responsive-mobile.png shows broken layout at 375px width
- test-results.json shows 3 console errors, 2.1s load time
Blocking issues: 4
感情なし。意見なし。ただ証拠のみ。
このチュートリアルでは、APIテストパイプラインを補完する証拠に基づくQAワークフローを構築します。フロントエンドのレイアウトを検証する場合でも、ApidogでAPI応答を確認する場合でも、原則は同じです。承認前に証拠を要求することです。Playwrightを自動スクリーンショットキャプチャ用にセットアップし、必須の現実確認コマンドを作成し、エージェントの主張を実際のコードと照合し、出荷前にPASS/FAIL認定を要求します。
なぜ証拠が重要なのか
AIエージェントは人に喜ばれたがります。助けたい、好かれたいと思っています。だから、都合の良いことを言います。
- 「コードはしっかりしています!」(テストされたことはない)
- 「パフォーマンスは素晴らしいはずです!」(測定されたことはない)
- 「完全にレスポンシブです!」(モバイルで確認されたことはない)
証拠に基づくQAはこれを変えます。意見の代わりに、次のものが得られます。
- デスクトップ、タブレット、モバイルのブレークポイントでのスクリーンショット
- 実際のページロードからのパフォーマンスメトリクス
- 機能が存在すること(または存在しないこと)を証明するgrep結果
- ヘッドレスブラウザテストからのコンソールエラー数
もう「私を信じて」ではありません。ただ証拠のみ。
ステップ1: Playwrightをセットアップする
Playwrightをインストールします。
npm install -D @playwright/test
npx playwright install chromium
qa-playwright.config.tsを作成します。
import { defineConfig } from '@playwright/test';
export default defineConfig({
testMatch: '**/qa-screenshots.spec.ts',
timeout: 30000,
use: {
baseURL: process.env.BASE_URL || 'http://localhost:8000',
screenshot: 'on',
trace: 'on-first-retry',
headless: true,
},
projects: [
{
name: 'desktop',
use: { viewport: { width: 1920, height: 1080 } },
},
{
name: 'tablet',
use: { viewport: { width: 768, height: 1024 } },
},
{
name: 'mobile',
use: { viewport: { width: 375, height: 667 } },
},
],
reporter: [['json', { outputFile: 'public/qa-screenshots/test-results.json' }]],
outputDir: 'public/qa-screenshots',
});
ステップ2: スクリーンショットテストスイートを作成する
qa-screenshots.spec.tsを作成します。
import { test, expect } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';
// Ensure output directory exists
const outputDir = 'public/qa-screenshots';
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
test.describe('Reality Check Screenshots', () => {
test('capture full page at all breakpoints', async ({ page, browserName }) => {
const errors: string[] = [];
const consoleLogs: string[] = [];
// Capture console errors
page.on('console', msg => {
if (msg.type() === 'error') {
consoleLogs.push(`[ERROR] ${msg.text()}`);
}
});
// Capture network failures
page.on('requestfailed', request => {
errors.push(`[NETWORK] ${request.url()} failed`);
});
// Navigate to page
await page.goto('/');
await page.waitForLoadState('networkidle');
// Capture performance metrics
const metrics = await page.metrics();
const performance = {
jsHeapSize: metrics.JSHeapUsedSize,
loadTime: await page.evaluate(() => performance.timing.loadEventEnd - performance.timing.navigationStart),
domContentLoaded: await page.evaluate(() => performance.timing.domContentLoadedEventEnd - performance.timing.navigationStart),
};
// Save screenshot
const projectName = browserName || 'chromium';
await page.screenshot({
path: path.join(outputDir, `full-page-${projectName}.png`),
fullPage: true,
});
// Save metrics
fs.writeFileSync(
path.join(outputDir, 'performance-metrics.json'),
JSON.stringify({ performance, consoleErrors: consoleLogs, networkErrors: errors }, null, 2)
);
});
test('capture responsive layouts', async ({ page }) => {
const breakpoints = [
{ name: 'desktop', width: 1920, height: 1080 },
{ name: 'tablet', width: 768, height: 1024 },
{ name: 'mobile', width: 375, height: 667 },
];
for (const breakpoint of breakpoints) {
await page.setViewportSize({ width: breakpoint.width, height: breakpoint.height });
await page.goto('/');
await page.waitForLoadState('networkidle');
await page.screenshot({
path: path.join(outputDir, `responsive-${breakpoint.name}.png`),
fullPage: true,
});
}
});
test('capture navigation interactions', async ({ page }) => {
await page.goto('/');
// Find and click navigation items
const navItems = await page.$$('nav a, header a, .nav a');
for (let i = 0; i < Math.min(navItems.length, 5); i++) {
await page.screenshot({ path: path.join(outputDir, `nav-${i}-before.png`) });
await navItems[i].click();
await page.waitForLoadState('networkidle');
await page.screenshot({ path: path.join(outputDir, `nav-${i}-after.png`) });
await page.goBack();
await page.waitForLoadState('networkidle');
}
});
test('capture form interactions', async ({ page }) => {
await page.goto('/');
// Find forms
const forms = await page.$$('form');
for (let i = 0; i < forms.length; i++) {
const form = forms[i];
await form.screenshot({ path: path.join(outputDir, `form-${i}-initial.png`) });
// Fill inputs
const inputs = await form.$$('input[type="text"], input[type="email"], input[type="password"]');
for (const input of inputs) {
await input.fill('test@example.com');
}
await form.screenshot({ path: path.join(outputDir, `form-${i}-filled.png`) });
}
});
test('capture accordion/dropdown interactions', async ({ page }) => {
await page.goto('/');
// Find accordions
const accordions = await page.$$('[data-accordion], details, .accordion');
for (let i = 0; i < accordions.length; i++) {
await accordions[i].screenshot({ path: path.join(outputDir, `accordion-${i}-closed.png`) });
await accordions[i].click();
await page.waitForTimeout(300);
await accordions[i].screenshot({ path: path.join(outputDir, `accordion-${i}-open.png`) });
}
});
});
ステップ3: 現実確認スクリプトを作成する
qa-playwright-capture.shを作成します。
#!/usr/bin/env bash
#
# qa-playwright-capture.sh — Run Playwright screenshot captures for reality checking
#
# Usage: ./qa-playwright-capture.sh [BASE_URL] [OUTPUT_DIR]
#
set -euo pipefail
BASE_URL="${1:-http://localhost:8000}"
OUTPUT_DIR="${2:-public/qa-screenshots}"
echo "Starting Reality Check screenshot capture..."
echo " Base URL: $BASE_URL"
echo " Output: $OUTPUT_DIR"
# Ensure output directory exists
mkdir -p "$OUTPUT_DIR"
# Run Playwright tests
export BASE_URL
npx playwright test --config=qa-playwright.config.ts --grep "@screenshot"
# Generate summary
echo ""
echo "Generating summary..."
# Count screenshots
SCREENSHOT_COUNT=$(find "$OUTPUT_DIR" -name "*.png" | wc -l)
echo " Screenshots captured: $SCREENSHOT_COUNT"
# Check for console errors
if [ -f "$OUTPUT_DIR/performance-metrics.json" ]; then
ERROR_COUNT=$(cat "$OUTPUT_DIR/performance-metrics.json" | grep -c '"\[ERROR\]"' || echo "0")
echo " Console errors: $ERROR_COUNT"
fi
# Check load time
if [ -f "$OUTPUT_DIR/performance-metrics.json" ]; then
LOAD_TIME=$(cat "$OUTPUT_DIR/performance-metrics.json" | grep -o '"loadTime": [0-9.]*' | head -1 | awk '{print $2}')
echo " Load time: ${LOAD_TIME:-N/A}ms"
fi
echo ""
echo "Reality Check complete. Review screenshots in: $OUTPUT_DIR"
echo ""
echo "Next step: Run Reality Checker agent to validate evidence"
実行可能にします。
chmod +x qa-playwright-capture.sh
ステップ4: 現実確認コマンドを実行する
AIエージェントが作業を承認する前に、以下のコマンドを実行します。
# 1. 実際に構築されたものを確認する
ls -la resources/views/ || ls -la *.html
ls -la src/components/ || ls -la components/
# 2. 主張された機能を相互参照する
grep -r "glassmorphism\|backdrop-filter\|blur" . --include="*.css" --include="*.html" || echo "NO GLASSMORPHISM FOUND"
grep -r "responsive\|media-query\|@media" . --include="*.css" || echo "NO RESPONSIVE CSS FOUND"
grep -r "jwt\|authentication\|auth" . --include="*.ts" --include="*.js" || echo "NO AUTH FOUND"
# 3. スクリーンショットキャプチャを実行する
./qa-playwright-capture.sh http://localhost:8000 public/qa-screenshots
# 4. 証拠を確認する
ls -la public/qa-screenshots/
# 期待されるファイル:
# - responsive-desktop.png
# - responsive-tablet.png
# - responsive-mobile.png
# - nav-*-before.png, nav-*-after.png
# - form-*-initial.png, form-*-filled.png
# 5. メトリクスを確認する
cat public/qa-screenshots/test-results.json
cat public/qa-screenshots/performance-metrics.json
ステップ5: Reality Checkerエージェントを起動する
Claude Codeセッションを開きます。
Activate Reality Checker mode.
Run your mandatory reality check process:
1. Verify files exist: ls -la src/components/
2. Cross-reference claimed features: grep for "premium", "glassmorphism"
3. Review screenshot evidence: public/qa-screenshots/
4. Check test-results.json for metrics
Project URL: http://localhost:8000
Output: PASS or NEEDS WORK with specific blocking issues.
期待される出力:
## Reality Check Results (現実確認結果)
### File Verification: PASS (ファイル検証: 合格)
- Component files present: 12 files found (コンポーネントファイルが存在: 12個のファイルが見つかりました)
- Expected structure matches (期待される構造と一致)
### Feature Verification: NEEDS WORK (機能検証: 作業が必要)
- Claimed: "Premium glassmorphism design" (主張: 「プレミアムなグラスモーフィズムデザイン」)
- grep result: NO GLASSMORPHISM FOUND (grep結果: グラスモーフィズムは見つかりませんでした)
- Status: CLAIM NOT SUPPORTED (ステータス: 主張がサポートされていません)
### Screenshot Evidence: NEEDS WORK (スクリーンショット証拠: 作業が必要)
- Desktop (1920x1080): Layout correct (レイアウトは正しい)
- Tablet (768x1024): Navigation overlap detected (ナビゲーションの重複を検出)
- Mobile (375x667): Product grid broken (2 columns instead of 1) (プロダクトグリッドが壊れている (1列ではなく2列))
### Performance Metrics: NEEDS WORK (パフォーマンスメトリクス: 作業が必要)
- Load time: 2.3s (target: <1s) (ロード時間: 2.3秒 (目標: 1秒未満))
- Console errors: 3 (target: 0) (コンソールエラー: 3 (目標: 0))
- Network failures: 1 (target: 0) (ネットワーク障害: 1 (目標: 0))
## Final Status: NEEDS WORK (最終ステータス: 作業が必要)
### Blocking Issues: (ブロックする問題)
1. Glassmorphism claimed but not implemented (グラスモーフィズムが主張されているが実装されていない)
2. Mobile layout broken at 375px (モバイルレイアウトが375pxで崩れている)
3. Load time exceeds 1s target (ロード時間が目標の1秒を超えている)
4. 3 console errors to fix (修正すべきコンソールエラーが3つ)
### Non-Blocking: (ブロックしない問題)
- Tablet navigation overlap (タブレットのナビゲーション重複)
- Add loading states (ローディング状態の追加)
Do not approve until blocking issues are resolved. (ブロックする問題が解決されるまで承認しないでください。)
ステップ6: 主張と証拠を相互参照する
主張チェックリストを作成します。
## Claims vs. Evidence Checklist (主張と証拠のチェックリスト)
| Claim (主張) | Evidence Command (証拠コマンド) | Result (結果) |
|---------------------|---------------------------------|---------------------------------|
| "Premium glassmorphism" (プレミアムなグラスモーフィズム) | grep "backdrop-filter" | NOT FOUND (見つからない) |
| "Fully responsive" (完全にレスポンシブ) | responsive-mobile.png | FAIL (broken grid) (失敗 (グリッド崩れ)) |
| "No console errors" (コンソールエラーなし) | test-results.json | 3 errors found (3つのエラーが見つかった) |
| "Fast load time" (高速なロード時間) | performance-metrics.json | 2.3s (target: <1s) (2.3秒 (目標: 1秒未満)) |
| "JWT authentication" (JWT認証) | grep "jsonwebtoken" | FOUND (見つかった) |
| "Rate limiting" (レート制限) | grep "rateLimit" | NOT FOUND (見つからない) |
プロジェクトごとにこのチェックリストを更新します。すべての主張について証拠を要求します。
現実確認ワークフローの完了
┌─────────────────────────────────────────────────────────────────┐
│ 1. Developer/AI completes work (開発者/AIが作業を完了する) │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 2. Run reality check commands (現実確認コマンドを実行する) │
│ - ls to verify files (ファイルを確認するためにls) │
│ - grep to verify features (機能を検証するためにgrep) │
│ - Playwright for screenshots (スクリーンショットのためにPlaywright) │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 3. Activate Reality Checker agent (Reality Checkerエージェントを起動する) │
│ - Review file verification (ファイル検証を確認する) │
│ - Cross-reference claims (主張を相互参照する) │
│ - Analyze screenshots (スクリーンショットを分析する) │
│ - Check metrics (メトリクスを確認する) │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 4. Output: PASS or NEEDS WORK (出力: PASSまたはNEEDS WORK) │
│ - PASS: Ship with confidence (PASS: 自信を持ってリリース) │
│ - NEEDS WORK: Fix blocking issues, re-run (NEEDS WORK: ブロックする問題を修正し、再実行する) │
└─────────────────────────────────────────────────────────────────┘
CI/CDとの統合
CIパイプラインに現実確認を追加します。
# .github/workflows/qa-reality-check.yml
name: Reality Check
on: [pull_request]
jobs:
reality-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Install Playwright
run: npx playwright install chromium
- name: Start server
run: npm start &
env:
PORT: 8000
- name: Wait for server
run: sleep 5
- name: Run reality check screenshots
run: ./qa-playwright-capture.sh http://localhost:8000 public/qa-screenshots
- name: Upload screenshots
uses: actions/upload-artifact@v4
if: always()
with:
name: reality-check-screenshots
path: public/qa-screenshots/
- name: Check for console errors
run: |
ERRORS=$(cat public/qa-screenshots/performance-metrics.json | grep -c '"\[ERROR\]"' || echo "0")
if [ "$ERRORS" -gt "0" ]; then
echo "Console errors found: $ERRORS"
exit 1
fi
- name: Check load time
run: |
LOAD_TIME=$(cat public/qa-screenshots/performance-metrics.json | grep -o '"loadTime": [0-9.]*' | head -1 | awk '{print $2}')
if (( $(echo "$LOAD_TIME > 1000" | bc -l) )); then
echo "Load time too slow: ${LOAD_TIME}ms (target: <1000ms)"
exit 1
fi
構築したもの
| コンポーネント | 目的 |
|---|---|
| Playwright設定 | 3つのブレークポイントでの自動スクリーンショットキャプチャ |
| テストスイート | フルページ、レスポンシブ、インタラクション |
| 現実確認スクリプト | ワンコマンドでの証拠収集 |
| 主張チェックリスト | AIの主張とgrep結果の相互参照 |
| CI/CD統合 | PRでの自動現実確認 |
次のステップ
ワークフローを拡張する:
- パフォーマンススコアのためのLighthouse統合を追加する
- アクセシビリティ監査(axe-core)を追加する
- ビジュアルリグレッションテスト(ピクセル比較)を追加する
主張データベースを構築する:
- すべてのAIの主張を証拠ステータスとともに記録する
- どのエージェントが最も幻覚を見やすいかを追跡する
- 時間経過に伴う精度スコアを作成する
チームと共有する:
- 現実確認プロセスを文書化する
- PR承認前に証拠を要求する
- 「スクリーンショットを見せて」をチームの習慣にする
よくある問題のトラブルシューティング
Playwrightテストのタイムアウト:
- 設定のタイムアウトを増やす:
timeout: 60000 - サーバーが実行中か確認:
curl http://localhost:8000 - ネットワークアイドル状態の待機時間を長くする:
await page.waitForLoadState('networkidle', { timeout: 30000 }) - デバッグのためにヘッデッドモードで実行:
npx playwright test --headed
スクリーンショットがキャプチャされない:
- 出力ディレクトリが存在し、書き込み可能か確認:
mkdir -p public/qa-screenshots - ファイル権限を確認:
chmod 755 public/qa-screenshots - Chromiumがインストールされているか確認:
npx playwright install chromium - デバッグ出力付きで実行:
DEBUG=pw:api npx playwright test
コンソールエラーがキャプチャされない:
- ナビゲーションの前にリスナーを追加:
page.goto()の前にpage.on('console', ...) - エラータイプフィルタリングを確認:
msg.type() === 'error' - デバッグのためにすべてのコンソールメッセージをログ出力:
page.on('console', msg => console.log(msg.text())) - ページが実際にコンテンツをロードしているか確認(空白のスクリーンショットではないこと)
モバイルのスクリーンショットがデスクトップレイアウトを表示する:
- ナビゲーションの前にビューポートが設定されていることを確認
- モバイルユーザーエージェントを追加:
await page.setUserAgent('Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)') - デバイスエミュレーションを使用:
use: { ...devices['iPhone 12'] } - HTML内のレスポンシブメタタグを確認:
<meta name="viewport" content="width=device-width">
UbuntuでCI/CDパイプラインが失敗する:
- システム依存関係をインストール:
sudo apt-get install -y libnss3 libnspr4 libatk1.0-0 - Playwrightの公式イメージを使用:
mcr.microsoft.com/playwright:v1.40.0-jammy - ブラウザをインストールする前に
npx playwright install-depsを実行 - コンテナ化された環境では
--no-sandboxフラグを追加
高度な現実確認パターン
パターン1: ビジュアルリグレッションテスト
ベースラインとスクリーンショットを比較して意図しない変更を検出します。
import { expect } from '@playwright/test';
test('visual regression check', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage-base.png', {
maxDiffPixels: 100, // Allow minor differences (軽微な差異を許容)
fullPage: true,
});
});
パターン2: アクセシビリティ監査
アクセシビリティの証拠のためにaxe-coreを統合します。
import AxeBuilder from '@axe-core/playwright';
test('accessibility audit', async ({ page }) => {
await page.goto('/');
const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
// Save results (結果を保存)
const fs = require('fs');
fs.writeFileSync(
'public/qa-screenshots/accessibility-results.json',
JSON.stringify(accessibilityScanResults, null, 2)
);
// Fail if critical violations (重大な違反がある場合は失敗)
const criticalViolations = accessibilityScanResults.violations.filter(
v => v.impact === 'critical' || v.impact === 'serious'
);
expect(criticalViolations).toHaveLength(0);
});
パターン3: パフォーマンス予算の強制
パフォーマンスしきい値を超えるビルドを失敗させます。
test('performance budget', async ({ page }) => {
await page.goto('/');
const metrics = await page.metrics();
const loadTime = await page.evaluate(() =>
performance.timing.loadEventEnd - performance.timing.navigationStart
);
// Budget thresholds (予算のしきい値)
expect(loadTime).toBeLessThan(2000); // 2s max (最大2秒)
expect(metrics.JSHeapUsedSize).toBeLessThan(5 * 1024 * 1024); // 5MB max (最大5MB)
});
あなたのAIエージェントはもう「素晴らしいですね」で済ませることはできません。彼らはスクリーンショット、メトリクス、grep結果で彼らの仕事を証明しなければなりません。
もう幻覚なし。もう幻想的な承認なし。ただ証拠のみ。
それが証拠に基づくQAの姿です。コマンドを実行し、スクリーンショットを確認し、証拠を要求するのです。
あなたの番です。ワークフローに現実確認を追加してください。自信を持ってリリースしましょう。
FAQ
AIエージェントはコードレビュー時に幻覚を見るのはなぜですか?
AIエージェントは協力的で好意的であるように訓練されています。彼らは検証されたものよりも、都合の良いことに応答します。証拠の要件がない場合、彼らは対立を避けるために「素晴らしいですね」と言います。
Playwrightをスクリーンショットテスト用にセットアップするにはどうすればよいですか?
npm install -D @playwright/test でインストールし、npx playwright install chromium を実行し、ビューポートのブレークポイントを持つ設定ファイルを作成し、各ブレークポイントでスクリーンショットをキャプチャするテストスイートを記述します。
承認前にどのような現実確認コマンドを実行すべきですか?
ls を実行してファイルが存在するか確認し、grep でコード内に主張された機能が存在するか確認し、Playwrightテストでスクリーンショットを取得し、test-results.json でコンソールエラーとパフォーマンスメトリクスを確認します。
Reality Checkerエージェントとは何ですか?
Reality Checkerは、The Agencyの専門的なAIエージェントであり、証拠を使用して作業を検証します。検証コマンドを実行し、スクリーンショットをレビューし、主張を相互参照し、特定のブロックする問題とともにPASSまたはNEEDS WORKを出力します。
現実確認をCI/CDに統合するにはどうすればよいですか?
Playwrightをインストールし、サーバーを起動し、スクリーンショットキャプチャを実行し、アーティファクトをアップロードし、コンソールエラーが0を超えるかロード時間がしきい値を超えた場合にビルドを失敗させるGitHub Actionsワークフローを追加します。
スクリーンショットに問題があるのにエージェントがPASSと言ったらどうすればよいですか?
エージェントが誤設定されています。Reality Checkerはステータスを出力する前に証拠をレビューする必要があります。(1) 機能を証明するgrep結果、(2) スクリーンショットのレビュー、(3) しきい値内のメトリクス、を要求するように再訓練してください。
チームに証拠に基づくQAを採用させるにはどうすればよいですか?
現実確認プロセスを文書化し、テストの合格を必須とするCI/CDゲートを追加し、PR承認にスクリーンショットレビューを義務付け、どのエージェントが最も正確な評価を出すかを追跡します。
Top comments (0)