目次
- はじめに
- テスト環境
- フェーズ1:テスト対象の棚卸し
- ソースコード全読み
- テスト計画の自動生成
- フェーズ2:全ルート巡回テスト
- HTTPステータス検証
- DOM構造チェック
- デッドリンクチェック
- フェーズ3:インタラクション検証
- FAQ(<details>要素)
- 検索モーダル(Pagefind)
- YouTubeファサードパターン
- コピーボタン(View Transitions後)
- ScrollToTopボタン
- フェーズ4:SEO・構造化データ監査
- OGPメタタグ
- 構造化データ(JSON-LD)
- サイトマップ
- フェーズ5:アクセシビリティ検証
- フェーズ6:View Transitions遷移テスト
- フェーズ7:セキュリティヘッダー検証
- 発見したバグと修正
- バグ1:検索モーダルのレジリエンス不足
- バグ2:CSPヘッダーのGoogle系オリジン不足
- テスト手法の体系化
- レイヤー1:静的解析(ソースコード読み取り)
- レイヤー2:HTTP層テスト(全ルート巡回)
- レイヤー3:DOM層テスト(構造検証)
- レイヤー4:インタラクション層テスト(動作検証)
- レイヤー5:アクセシビリティ層テスト
- 制約と限界
- まとめ
はじめに
Webサイトの品質保証は、リリース前の一度きりのチェックでは不十分です。コンテンツの追加、ライブラリの更新、CDN設定の変更など、あらゆるタイミングで予期せぬ不具合が生まれます。
本記事では、VS Code のエージェントモード(GitHub Copilot) がブラウザを直接操作し、サイト全体をモンキーテストした実践記録をまとめます。ソースコードの静的解析からブラウザ上の動的検証まで、AIが一貫して実行したテスト手法を体系化しました。
テスト環境
| 項目 | 内容 |
|---|---|
| エディタ | VS Code + GitHub Copilot(エージェントモード) |
| AIモデル | Claude Opus 4.6 |
| ブラウザ操作 | VS Code内蔵Playwrightツール |
| テスト対象 | Astro + UnoCSS + Cloudflare Pages 構成の静的サイト |
| プレビュー | npm run preview(ローカル) + 本番URL |
エージェントモードでは、Copilotがターミナルコマンドの実行、ファイルの読み書き、ブラウザの操作を自律的に行います。テスターは「テストしてください」と指示するだけで、AIが以下の全工程を自動実行します。
フェーズ1:テスト対象の棚卸し
ソースコード全読み
AIはまず、プロジェクトのディレクトリ構造を走査し、すべてのコンポーネント・ページ・ユーティリティのソースコードを読み込みます。
src/
├── components/ ← 28コンポーネントを全読み
├── content/blog/ ← 16記事のフロントマターを解析
├── pages/ ← 全ルーティングファイルを把握
├── layouts/ ← BaseLayoutの構造を理解
└── utils/ ← rehypeプラグイン・OG画像生成を確認
この段階でAIは以下を自動的に把握します。
- 全ルート一覧:静的ページ7件 + ブログ関連ルート(記事・タグ・アーカイブ・著者・ページネーション)
- インタラクティブ要素:検索モーダル、FAQ開閉、コピーボタン、YouTubeファサード、スクロールトップ、ヒーロースライダー
- 外部連携:ssgform.com(フォーム)、Cloudflare Turnstile(ボット対策)、Google AdSense、GA4
テスト計画の自動生成
ソースコードの分析結果から、AIはテスト計画をTodoリストとして自動生成します。人間がチェックリストを作る必要はありません。
フェーズ2:全ルート巡回テスト
HTTPステータス検証
ビルド済みサイトをnpm run previewで起動し、Playwrightで全ルートにアクセスします。
テスト対象:31ルート
├── 静的ページ 7件(/, /about/, /services/ など)
├── ブログ記事 16件
├── タグページ 24件
├── アーカイブ 4件
├── ページネーション 2件(/blog/page/2/, /blog/page/3/)
├── 著者ページ 2件
├── RSS 1件
└── 404テスト 1件
結果:全ルート200 OK(意図的404を除く)
DOM構造チェック
各ページで以下を自動検証します。
| チェック項目 | 検証方法 | 結果 |
|---|---|---|
| 壊れた画像 | img.complete && img.naturalWidth === 0 | 0件 |
| 空リンク | href が空・#・未設定 | 0件 |
| unsafe外部リンク | target="_blank" に rel="noopener" なし | 0件 |
| H1の数 | document.querySelectorAll('h1').length === 1 | 全ページOK |
| スキップリンク | 「本文へスキップ」の存在 | 全ページOK |
| lang属性 | html[lang="ja"] | 全ページOK |
デッドリンクチェック
起点ページから内部リンクを再帰的に収集し、55件のユニークURLすべての到達を確認。デッドリンクは0件でした。
フェーズ3:インタラクション検証
AIはPlaywrightでブラウザ要素を直接操作し、JavaScriptで動作する機能を検証します。
FAQ(<details>要素)
// AIが実行したテストコードの例
const details = document.querySelectorAll('details');
// 初期状態:すべて閉じている → OK
// クリックで開く → OK
// 再クリックで閉じる → OK
検索モーダル(Pagefind)
window.openSearch()で検索ダイアログを開く- Pagefind UIのロード完了を待機
- 「Astro」と入力して検索結果が表示されることを確認
- ESCキーで閉じることを確認
YouTubeファサードパターン
.yt-facade要素をクリックyoutube-nocookie.com/embed/のiframeが動的に生成されることを確認autoplay=1パラメータが付与されていることを確認
コピーボタン(View Transitions後)
View Transitionsでページ遷移したあとに、コードブロックのコピーボタンが再初期化されて動作することを確認。astro:page-loadイベントでの再登録が正しく機能していました。
ScrollToTopボタン
ページ末尾までスクロール → ボタンが表示される → クリック → window.scrollY が0に戻ることを確認。
フェーズ4:SEO・構造化データ監査
OGPメタタグ
全ページで以下を検証しました。
og:title/og:description/og:image/og:url/og:typeが設定されているtwitter:cardがsummary_large_imageに設定されているcanonicalURLが正しい- OG画像のURLが実在し、推奨サイズ(1200×630)である
構造化データ(JSON-LD)
各ページのJSON-LDを解析し、スキーマの種別と内容を検証しました。
| ページタイプ | 構造化データ |
|---|---|
| 全ページ共通 | Organization, WebSite |
| ブログ記事 | BreadcrumbList, BlogPosting, FAQPage |
| FAQ付き記事 | FAQPage(mainEntityに質問と回答が含まれる) |
サイトマップ
sitemap-index.xml → sitemap-0.xml で全57URLが登録されていることを確認。robots.txt からサイトマップへの参照も正常でした。
フェーズ5:アクセシビリティ検証
AXEエンジン相当のチェックを、Playwrightで複数ページに対して実行しました。
| チェック項目 | 対象ページ数 | 違反数 |
|---|---|---|
| img要素のalt属性 | 4 | 0 |
| button要素のラベル | 4 | 0 |
| 見出し階層(h1→h2→h3の順序) | 4 | 0 |
| フォームinputのlabel | 1(お問い合わせ) | 0 |
| ランドマーク要素 | 4 | 0 |
| 外部リンクのrel属性 | 4 | 0 |
| tabindex値の適正 | 4 | 0 |
全4ページ、全チェック項目で違反ゼロという結果でした。
フェーズ6:View Transitions遷移テスト
Astro View Transitionsによるページ遷移では、DOMが差分更新されるためJavaScriptの再初期化が課題になります。以下の遷移パターンを検証しました。
ホーム → ブログ一覧 → 記事 → タグ → 著者 → コンタクト → サービス → ホーム
各遷移後に確認した項目:
- URL・タイトル・H1が正しく更新される
- 検索ボタンが動作する
- コピーボタンが再初期化される
- パンくずナビが更新される
- JSエラーがゼロ
フェーズ7:セキュリティヘッダー検証
本番サイトのレスポンスヘッダーを検証した結果:
| ヘッダー | 値 | 評価 |
|---|---|---|
| Content-Security-Policy | フル設定済み | ◎ |
| X-Frame-Options | SAMEORIGIN | ◎ |
| X-Content-Type-Options | nosniff | ◎ |
| Strict-Transport-Security | max-age=15552000 | ○ |
| Referrer-Policy | strict-origin-when-cross-origin | ◎ |
| Permissions-Policy | geolocation=(), camera=() 等 | ◎ |
発見したバグと修正
今回のテストで2件のバグを発見し、セッション内で修正まで完了しました。
バグ1:検索モーダルのレジリエンス不足
症状:Pagefindスクリプトの読み込みが完了する前に検索ボタンを押すと、UIが応答しない。
原因:loadPagefindScript() が一度failしたあと、リトライする仕組みがなかった。
修正:失敗時にPromiseキャッシュをクリアし、ユーザーに「再読み込み」ボタンを表示するフォールバックUIを実装。
バグ2:CSPヘッダーのGoogle系オリジン不足
症状:Google AdSense関連のリソースがCSPでブロックされ、コンソールにエラーが表示される。
原因:connect-src と frame-src に https://www.google.com / https://www.google.co.jp が含まれていなかった。
修正:public/_headers のCSPディレクティブにGoogle系オリジンを追加。
テスト手法の体系化
このAIモンキーテストの手法を整理すると、以下のレイヤーに分類できます。
レイヤー1:静的解析(ソースコード読み取り)
- ディレクトリ構造の走査
- コンポーネントの依存関係把握
- フロントマタースキーマ(Zod)の解析
- CSP・リダイレクト設定の確認
レイヤー2:HTTP層テスト(全ルート巡回)
- ステータスコード検証(200/404/301)
- レスポンスヘッダー監査(セキュリティ・キャッシュ)
- サイトマップ・robots.txt・ads.txt の整合性
レイヤー3:DOM層テスト(構造検証)
- 壊れた画像・空リンク・unsafe外部リンク
- H1の一意性・見出し階層
- メタタグ(OGP・canonical・description)
- 構造化データ(JSON-LD)
レイヤー4:インタラクション層テスト(動作検証)
- クリック・入力・キーボード操作
- モーダル開閉・フォームバリデーション
- View Transitions後のJS再初期化
- スクロールイベント・遅延読み込み
レイヤー5:アクセシビリティ層テスト
- alt属性・ラベル・ARIA
- 見出し階層・ランドマーク
- フォーカス管理・tabindex
- スキップリンク
制約と限界
AIモンキーテストにはいくつかの制約があります。
| 制約 | 詳細 |
|---|---|
| ビューポートエミュレーション | VS Code内蔵ブラウザではモバイル幅のエミュレーションが効かない。CSSの正当性はビルド出力の静的解析で代替した |
| ネットワーク状態 | オフライン・低速回線のシミュレーションは不可。Service Workerのテストも対象外 |
| ユーザーの「感覚」 | デザインの美しさ・読みやすさ・ブランドとの一貫性は人間の判断が必要 |
| 認証フロー | ログインが必要なページは、認証情報の安全な管理が別途必要 |
CSSのレスポンシブ対応は、ビルド出力のCSSファイルを直接解析し、@media(min-width:768px) のメディアクエリが正しく生成されていることを確認する方法で代替しました。
まとめ
GitHub Copilotのエージェントモードは、「テストしてください」という一言から、ソースコード分析→テスト計画→ブラウザ自動操作→バグ修正→再検証という一連のQAサイクルを完結させることができます。
今回の実績をまとめると以下のとおりです。
- テスト対象:31ルート + 24タグ + 4アーカイブ + 2ページネーション = 61ルート
- テスト項目:HTTPステータス、DOM構造、インタラクション、SEO、アクセシビリティ、セキュリティ、View Transitions
- 発見バグ:2件(検索モーダル、CSPヘッダー)→ その場で修正
- アクセシビリティ違反:0件
- デッドリンク:0件
人間の目視確認とAIの自動検証を組み合わせることで、テストの網羅性と効率を両立できます。
AIモンキーテストの進め方
棚卸し
ソースコードを全読みし、テスト対象となるルート・コンポーネント・インタラクションを洗い出す。
巡回テスト
全ルートにHTTPリクエストを送り、ステータスコード・壊れた画像・空リンクを検出する。
インタラクション検証
FAQ開閉・コピーボタン・検索モーダル・YouTube埋め込みなど、JSで動く要素を操作して確認する。
構造・SEO監査
構造化データ・OGP・メタタグ・見出し階層・アクセシビリティを全ページで検証する。
- ブラウザで1ページずつ目視確認
- チェックリストを手動で作成・管理
- 確認漏れが発生しやすい
- 再現手順の記録に時間がかかる
- 全ルートを自動巡回してHTTPステータス・DOM構造を検証
- AIがソースコードからテスト対象を自動抽出
- 壊れた画像・空リンク・JSエラーをゼロ見落としで検出
- 発見→原因特定→修正→再検証までをセッション内で完結
GitHub Copilotのエージェントモードは無料で使えますか?
Playwright以外のブラウザツールでも同じことができますか?
静的サイト以外にも適用できますか?
テストで見つかったバグの修正もAIに任せられますか?
Gui
Acecore 代表。システム開発・Web制作・インフラ運用からIT教育まで幅広く手がけるエンジニア。 技術で人と組織の課題を解きほぐすのが好き。