bughunt は何をしますか?
単体テストやほとんどのUIテストは、その作者が考えたコードパスのみをチェックし、実際のクリックやキー入力をスキップするテストフックを使うことがよくあります。しかし、ユーザーはそのようにアプリを使いません。ユーザーはフックが届かない場所をクリックし、すべての操作の後にUndoを押し、狭いウィンドウで作業し、途中でネットワークが切断され、同僚が送ってきた奇妙なファイルを開きます。彼らが出会うバグのほとんどは元々存在していたものであり、それを監視するものは何もありませんでした。
このスキルは監視します。実際の入力を使用して実際のアプリを一度に1つのエリアずつ操作し、確認されたすべてのバグを2回記録します。リポジトリに残る失敗するテストとして(バグが気づかれずに戻ってくるのを防ぐため)、そしてリポジトリのバグリストへのエントリとして(誰かが修正するため)。ハントはプロダクトコードを修正しません。見つけ、証明し、書き留めるだけです。
モード
- Hunt(デフォルト): 1つのエリアを選び、それをハントし、結果を記録し、ローテーションを更新します。1回の実行で1つのエリアに絞ることで、実際のバグを見つけるのに十分な深さのハントが可能になります。
- Set up: リポジトリにアプリをエンドツーエンドで駆動する方法がない、または
references/boundaries.mdに境界が定義されていない場合。すべてのサーフェスで1つの機能を実行できる最小のウォークスルーレーンを構築し(references/walkthroughs.md)、その後ハントします。 - Sweep: 既存のすべてのウォークスルーを実行し、前回の実行から新しく追加されたもの、変更されたもの、修正されたものを報告します。スイープは新しい種類のバグではなく、リグレッションを見つけます。ハントと組み合わせて使用します。
- Rules:
references/invariants.mdにあるルールの1つをレーンに追加し、すべてのウォークスルーのすべてのステップで実行されるようにします。1つのルール(例:「Undoは正確に前の状態を復元する」)だけで、誰もスクリプト化しようとしない機能全体にわたって数十のバグを表面化させることができます。
1. まず基本ルールを学ぶ
リポジトリの指示ファイル(CLAUDE.md、AGENTS.md、CONTRIBUTING、ルールやハンドオフノート)、アプリを実行するもののREADME、既存のエンドツーエンドテストを読んでください。以下を確認します。
- アプリの各サーフェスを起動する方法: 開発サーバー、デスクトップビルド、モバイルシミュレーター。サーフェスとは、1つのホスト(Web、デスクトップ、モバイル)における1つの外観(ライト、ダーク、ハイコントラスト)および1つのサイズ(ワイド、ナロー、電話)を指します。
- バグがどこで追跡されているか(バグファイル、ToDoリスト、課題トラッカー)と、そこで使用されているエントリのフォーマット。そのフォーマットで記述します。
- テストが決して触れてはならないもの: 実際のアカウント、実際のユーザーファイル、本番データ、実際のメール、支払い、ユーザーのクリップボード、プリンター、ブラウザ、インストール済みのアプリのコピー。
references/boundaries.mdを読み、何かを駆動する前に該当するすべての境界を適用してください。これはハントの中で実際の損害を与える可能性がある部分なので、最初に行います。 - リポジトリが他に禁止しているもの(プッシュ、ネットワークアクセス、有料サービス、エージェントの起動など)がないか確認します。それらのルールはこのスキルよりも優先されます。
答えが何に触れてもよいかを変える場合にのみ質問してください。それ以外は選択し、その仮定をハントレポートに記述します。
2. エリアを選択し、その機能をリストアップする
指定されたエリアを使用します。それ以外の場合はbughunt/areas.mdを読み(初回実行時はtemplates/areas.mdから作成)、次の優先順位で選択します: まだハントされていないエリア、前回のハントから変更されたエリア(パスをgit logで確認)、最も古いエリア。エリアとは、ユーザーが一緒に使用する機能のセットです: ドキュメントエディター、ファイルブラウザ、サインインとアカウント、設定、共有、支払い。
リポジトリにあるもの(機能レジストリ、メニューとコマンドリスト、ルート、ヘルプページ、コードのエントリポイント)から、エリアの機能をリストアップします。各機能は、すべてのサーフェスで少なくとも1回はテストされます。
3. ハント
各機能について、まずユーザーが何をするかを、現実的な合成ファイルを使用して最初から最後まで実行します。次に、references/checklist.mdに従って作業します。これは、アプリを繰り返し壊す敵意のあるユーザーの行動のリストです: すべてのステップの後にUndo、キーボードのみ、狭いウィンドウ、ダークモード、途中でのオフライン、最も大きくて最も壊れたファイル、別のフォーマットを介したラウンドトリップ、2つのタブで同じこと、意図的な失敗。
実際の入力イベント(クリック、キー押下、ドラッグ、タイピング)を使用して、人間のペースでアプリを操作します。スクリプトは人間よりも速く動作するため、クリックの後は次のアクションの前に短い間隔を置き、別々にUndoすることを期待する2つの変更の間は半秒の間隔を空けます。そうしないと、タイミングアーティファクトをバグとして報告してしまいます。
すべてのステップで以下を監視します:
- 間違った結果、または持続しない正しい結果(リロード、保存、Undo、タブの切り替え後に消える)
- 失われた作業: 編集、設定、選択、スクロール位置
- 多すぎる、少なすぎる、またはまったく元に戻さないUndo
- 何もしないコマンド、エントリポイントの1つからのみ機能するコマンド、実行できないときに無効化されていないコマンド
- 生のエラーテキスト: スタックトレース、エラーコード、内部パス
- コンソールエラー、クラッシュ、空白のウィンドウ、ハング
- 薄すぎる、クリップされている、重なっている、または単語の途中で途切れているテキスト(
references/invariants.mdのスクリーンショットチェックがこれらのほとんどを自動的にキャッチします) - 別のサーフェスで異なる動作をする同じステップ
各候補を見つけたら、サーフェス、ステップ、期待した結果とともに書き留めてください。その後続行します。機能の最後に確認します。
4. 報告前に確認する
ハントの価値は、その発見が真実であるかどうかにかかっています。各候補について:
- クリーンな状態から2回再現する、人間のペースで、手動または最小限のスクリプトを使用して。再現できない場合は、破棄するか、見た内容と場所を「未確認:」として報告します。
- テスト自体の問題を除外する。タイミング(上記参照)、間違った要素に一致したセレクター、テスト自身のスタブ、フォーカスされていなかったウィンドウ、ホバー状態の何かにポインターが置かれていたこと。ポインターの位置によって現れたり消えたりする発見は実際のバグですが、そのテストでは固定されたポインター位置が必要です。
- コストが低い場合は原因を特定する。該当すると思われるコードの箇所を読み、ファイル名と関数を特定します。ここに時間をかけすぎないでください。修正者は後で調査します。
- トラッカーを確認する。既存のエントリでカバーされている場合は、新しいエントリを作成する代わりに、新しいサーフェスや詳細をそのエントリに追加します。
- 原因ごとにグループ化する。複数の症状が1つの原因を共有することがよくあります(1つのキーバインディングの欠落が、1つのホスト上の5つのエディターでUndoを壊す可能性があります)。そのように記述することで、修正が1回で済むようにします。
5. 確認された各バグを記録する
- まず失敗するテスト。機能のウォークスルー(または新しいウォークスルー)にステップを追加し、その期待値として何が起こるべきかを記述します。実行して、それが失敗すること、そしてバグの理由で失敗し、他の理由ではないことを確認します。バグが修正されると、このテストはパスします。既存の期待値やスクリーンショットチェックを決して弱めて実行をパスさせないでください。チェックが間違っている場合は、レポートで理由を説明し、人間に判断を委ねます。
- 次にバグエントリ。リポジトリのバグリストの最後に、そのフォーマットで、
templates/bug-entry.mdを使用して追加します。ユーザーの言葉による症状、実際の動作と期待される動作、測定値、コード内の場所、それをガードするテスト、およびそれが現れるサーフェス。 - ハント中にプロダクトコードを変更しない。ただし、修正が依頼された場合は除きます。ハント中に修正を行うと、発見が隠され、2種類のレビューが混ざってしまいます。
- リポジトリのルールが許可する場合は、新しいテストとバグエントリをファイル名でステージングしてコミットします。依頼がない限りプッシュしないでください。
6. 報告とローテーション
templates/hunt-report.mdからハントレポートを作成します: エリア、サーフェス、テストとエントリを含むすべての発見、破棄した候補とその理由、テストできなかったこと、原因別の推奨修正グループ。bughunt/areas.mdのエリアの行を更新します(日付、コミット、発見)。
最後に、平易な言葉で次のことを伝えます: 確認されたバグの数、最悪の3つ、修正グループ、およびローテーションが次に選択するエリア。
見つけ続ける
完了したハントは、同じバグが戻ってくるのをキャッチするテストを残します。新しいバグには新しい監視が必要です:
- ローテーションで再度ハントします。大きな変更があった後はエリアを再ハントします。
- 新しい場所に繰り返し現れるバグをルール(
references/invariants.md)に変換し、すべてのステップでチェックされるようにします。 - ユーザーが報告したすべてのバグは、修正される前にウォークスルーステップになります。
- すべてのリリース前、およびリポジトリがスケジューラーを許可する場合は毎晩、レーン全体を実行します。新しい失敗と変更された失敗のみを報告し、既知のバグが新しいバグを埋もれさせないようにします。
作業が多い場合
作業を複数のモデルやセッションに分割できる場合は、最も強力なモデルでハントし、新しいセッションで別のモデルで確認します。2回目のパスでは、クリーンな状態から各失敗テストを再実行し、各エントリを冷たく読みます。これにより、1回のパスだけで保持されがちな自信過剰な誤検出をキャッチします。