dogfood について
Dogfood は browser_exec を使って Web アプリを体系的に探索テストする QA スキルです。テスト範囲の計画、操作確認、証拠収集、問題分類から、構造化されたバグレポートの作成までを案内します。
主な機能
- 01テスト範囲とページ網羅の計画
- 02操作とフォーム検証のテスト
- 03スクリーンショットとコンソールエラーの記録
- 04問題の分類と重複整理
- 05構造化 QA レポートの作成
活用シーン
- 01リリース前の Web アプリ探索テスト
- 02フォームや複数段階のユーザーフローのテスト
- 03証拠付きの再現可能な問題の記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nousresearch/ hermes-agent --skill dogfoodインストール後、Claude Code で/dogfoodを入力して読み込まれたか確認します。
同梱ファイルreferences/issue-taxonomy.mdtemplates/dogfood-report-template.md
詳細
Dogfood:Web アプリケーションの体系的な QA テスト
概要
このスキルでは、browser_exec を使って Web アプリケーションの探索的 QA テストを体系的に行う方法を説明します。アプリケーションを操作し、要素を操作して問題の証拠を記録し、構造化されたバグレポートを作成します。
前提条件
browserツールセット(browser_exec)が有効になっている必要があります。browser_execは、事前にインポートされたヘルパー(new_tab、goto_url、wait_for_load、page_info、js、fill_input、click_at_xy、capture_screenshot、cdp)を使って Python を実行します。ブラウザーの状態は呼び出し間で保持されますが、Python の変数は保持されません。- ユーザーから提供されたテスト対象の URL とテスト範囲
入力
ユーザーから次の情報が提供されます。
- 対象 URL — テストの開始地点
- 範囲 — テストに重点を置く領域/機能(包括的なテストを行う場合は「サイト全体」)
- 出力ディレクトリ(任意) — スクリーンショットとレポートの保存先(デフォルト:
./dogfood-output)
ワークフロー
次の 5 段階の体系的なワークフローに従います。
フェーズ 1:計画
- 出力ディレクトリの構成を作成します。
{output_dir}/ ├── screenshots/ # Evidence screenshots └── report.md # Final report (generated in Phase 5) - ユーザーの入力に基づいてテスト範囲を特定します。
- テストするページと機能を計画し、大まかなサイトマップを作成します。
- ランディング/ホームページ
- ナビゲーションリンク(ヘッダー、フッター、サイドバー)
- 主要なユーザーフロー(サインアップ、ログイン、検索、チェックアウトなど)
- フォームとインタラクティブ要素
- エッジケース(空の状態、エラーページ、404)
フェーズ 2:探索
各ステップの操作をまとめて、1 回の browser_exec 呼び出しで実行します。計画に含まれる各ページまたは機能について、次を行います。
-
コンソールフックを設定してからページに移動します。 ページ読み込み中に発生するエラーも捕捉できるよう、移動する前にタブへフックを登録します。
# Open page with console-error capture HOOK = """window.__qa_errors = []; const _e = console.error; console.error = (...a) => { window.__qa_errors.push(a.map(String).join(' ')); _e(...a); }; addEventListener('error', e => window.__qa_errors.push('uncaught: ' + e.message)); addEventListener('unhandledrejection', e => window.__qa_errors.push('rejection: ' + String(e.reason)));""" new_tab('about:blank') # first call only: the hook binds to the current tab cdp('Page.addScriptToEvaluateOnNewDocument', source=HOOK) goto_url("https://example.com/page") wait_for_load() print(page_info()) print(js('window.__qa_errors || []'))以降の呼び出しでページに移動する場合も、呼び出しの冒頭でフックを再登録します。表面化しない JS エラーは、価値の高い検出事項です。
-
ページ構造を確認します — 表示されているインタラクティブ要素と、そのビューポート内の中心座標を一覧表示します(ロール/名前が必要な場合は、
cdp('Accessibility.getFullAXTree')を使い、Python でフィルタリングします)。# List interactive elements print(js("""(() => [...document.querySelectorAll('a,button,input,select,textarea,[role=button]')] .filter(e => e.offsetParent).slice(0, 80).map((e, i) => { const r = e.getBoundingClientRect(); return {i, tag: e.tagName, text: (e.innerText || e.value || e.getAttribute('aria-label') || '').trim().slice(0, 60), id: e.id, name: e.name, x: Math.round(r.x + r.width / 2), y: Math.round(r.y + r.height / 2)}; }))()""")) -
ページを目視で評価します。
capture_screenshot()を呼び出し、添付画像を確認して、レイアウトの問題、壊れた要素、アクセシビリティ上の懸念がないか調べます。モデルが画像を表示できない場合は、出力されたパスをvision_analyzeに渡します。 -
インタラクティブ要素を体系的にテストします。
- ボタンとリンクをクリックします:
js("document.querySelector('#submit').click()")、またはステップ 2 で得た中心座標を使ってclick_at_xy(x, y)を実行します - フォームに入力します:
fill_input('input[name=email]', 'test input') - キーボード操作をテストします:
cdp('Input.dispatchKeyEvent', type='keyDown', key='Tab', code='Tab', windowsVirtualKeyCode=9)の後に対応するkeyUpを実行し、次にjs('document.activeElement.outerHTML.slice(0, 200)')を実行してフォーカス先を確認します。key='Enter'、code='Enter'、windowsVirtualKeyCode=13でも同じ手順を行います - コンテンツをスクロールします:
js('window.scrollBy(0, 800)') - 戻ります:
js('history.back()')を実行し、その後wait_for_load()を実行します - 無効な入力でフォームの検証をテストします
- 空のまま送信するテストを行います
- ボタンとリンクをクリックします:
-
各操作の後、同じ呼び出し内で次を確認します。
- コンソールエラー:
print(js('window.__qa_errors || []')) - 視覚的な変化:
capture_screenshot()を実行し、前のスクリーンショットと比較します - 期待される動作と実際の動作の比較(
page_info()、または関連要素を読み取るjs())
- コンソールエラー:
フェーズ 3:証拠の収集
見つかった問題ごとに、次を行います。
-
問題が分かるスクリーンショットを撮影します。
capture_screenshot()は保存先のパスを出力します。これを{output_dir}/screenshots/に、内容が分かる名前(例:issue-03-broken-login.png)でコピーします。このパスをレポートで参照します。 -
詳細を記録します。
- 問題が発生する URL
- 再現手順
- 期待される動作
- 実際の動作
- コンソールエラー(ある場合)
- スクリーンショットのパス
-
問題の分類体系(
references/issue-taxonomy.mdを参照)に従って問題を分類します。- 重大度:Critical / High / Medium / Low
- カテゴリー:機能 / ビジュアル / アクセシビリティ / コンソール / UX / コンテンツ
フェーズ 4:分類
- 収集したすべての問題を確認します。
- 重複を解消します。異なる箇所で発生している同じバグは、1つの問題にまとめます。
- 各問題に最終的な重大度とカテゴリを割り当てます。
- 重大度の高い順(Critical、High、Medium、Low)に並べます。
- エグゼクティブサマリー用に、重大度とカテゴリごとの問題数を集計します。
フェーズ 5:レポート
templates/dogfood-report-template.md のテンプレートを使用して、最終レポートを生成します。
レポートには次の項目を含めてください。
- エグゼクティブサマリー:問題の総数、重大度別の内訳、テスト範囲
- 問題ごとのセクション:以下を含めます。
- 問題番号とタイトル
- 重大度とカテゴリのバッジ
- 問題を確認した URL
- 問題の説明
- 再現手順
- 期待される動作と実際の動作
- スクリーンショットの参照(インライン画像には
MEDIA:<screenshot_path>を使用) - 該当する場合はコンソールエラー
- すべての問題のサマリーテーブル
- テストに関する注記:テストした内容、テストしていない内容、ブロッカー
レポートを {output_dir}/report.md に保存します。
ツールのリファレンス
すべてのブラウザー操作は browser_exec の呼び出しで行います。以下は、上記で使用しているヘルパーと慣用表現です。
| アクション | browser_exec の慣用表現 |
|---|---|
| URL に移動 | new_tab(url) を一度実行します(またはフックを登録する前に new_tab('about:blank') を実行します)。続いて goto_url(url) を実行し、wait_for_load() を呼び出します |
| ページの状態 | page_info() |
| DOM/アクセシビリティツリー | js(...) で抽出するか、Python で cdp('Accessibility.getFullAXTree') をフィルタリングします |
| クリック | js("document.querySelector(sel).click()") または click_at_xy(x, y) |
| 入力欄への入力 | fill_input(selector, text) |
| スクロール | js('window.scrollBy(0, 800)') |
| 戻る | js('history.back()') |
| キーの押下 | cdp('Input.dispatchKeyEvent', type='keyDown', key=..., code=..., windowsVirtualKeyCode=...) と keyUp |
| スクリーンショット | capture_screenshot()(結果に画像が添付されます。テキストのみを扱うモデルでは、パスに対して vision_analyze を使用します) |
| JS コンソールエラー | cdp('Page.addScriptToEvaluateOnNewDocument', source=HOOK) でフックし、`js('window.__qa_errors |
ヒント
- ページ遷移後と重要な操作の後には、必ず
window.__qa_errorsを読み取ってください。 サイレントな JS エラーは、特に価値のある発見の一つです。 - 各サブプロシージャを1回の
browser_exec呼び出しにまとめてください(移動、待機、抽出、操作、エラー確認)。往復回数を減らせ、フックも維持されます。 - 要素の位置を把握する必要がある場合や、DOM 抽出だけでは判断しにくい場合は、
capture_screenshot()を撮影してください。click_at_xyには、要素一覧に表示されている中心座標を指定します。 - 有効な入力と無効な入力の両方でテストしてください。 フォームのバリデーションに関するバグはよく発生します。
- 長いページはスクロールして確認してください。 スクロールしないと見えないコンテンツで、表示上の問題が発生している可能性があります。
- ナビゲーションの流れをテストしてください。 複数ステップのプロセスを最後まで実行します。
- スクリーンショットで確認できるレイアウトの問題を記録し、レスポンシブ動作を確認してください。
- エッジケースも忘れずに確認してください。 空の状態、非常に長いテキスト、特殊文字、連続クリックなどです。
- スクリーンショットをユーザーに報告するときは、証拠をインラインで表示できるように
MEDIA:<screenshot_path>を含めてください。