false-green-tests について
false-green-testsは、テストの成功がアプリの実際の動作を示すか確認するテストスキルです。Reticleでアプリの観測結果とテストの主張を照合し、観測可能な結果に基づくアサーションへの書き換えを案内します。
主な機能
- 01失敗しないアサーションの検出
- 02アプリのリクエストとモックの比較
- 03フレームワーク状態とUIの照合
- 04未読レスポンスと未検証画面の特定
- 05観測可能な結果に基づくテストの修正
活用シーン
- 01成功扱いのテストで動かないコントロールを調査
- 02アプリのリクエストとテスト用スタブを照合
- 03UIとストアの状態の食い違いを発見
- 04アプリ各画面のテストカバレッジを確認
MCP 対応
このスキルはReticleのツールで実行中のアプリを観測・操作し、ネットワーク、状態、カバレッジを確認します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ reticlehq/ reticle --skill false-green-testsインストール後、Claude Code で/false-green-testsを入力して読み込まれたか確認します。
詳細
テストスイートは成功しているのに、アプリは壊れている
テストの成功が示すのはテストについてであり、アプリについてではありません。このスキルでは、実際のアプリを実行し、その動作とテストが主張している内容を比較することで、この2つを切り分けます。
アプリの内部から実行中のアプリを観察する Reticle を使用します。対象は DOM、ネットワーク、コンソール、ルーティング、フレームワークの状態です。まだセットアップしていない場合は、reticle スキルに従ってください。Reticle をインストールし、init によるアプリのファイル変更前にユーザーに確認を求め、1つのフローを実証します。
確認する価値の高い順に並べた5つのパターン
1. アサーションが失敗しない。 ユーザーが信頼しているテストを読みます。存在しないことだけをアサートしている(コンソールエラーがない、例外がスローされない、Promise が拒否されない)場合、何にもつながっていないコントロールでもテストは成功します。動かないボタンは何もスローせず、何も発火せず、何も変化させません。代わりにアプリで実証します。
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "allOf", predicates: [
{ kind: "net", method: "POST", urlContains: "/api/...", status: 200 },
{ kind: "signal", name: "..." },
]}})
成功しているテストスイートに対して、ここで no という判定が出たなら、それが誤った成功です。
2. テストはモックを操作し、アプリは API を呼び出している。 アプリが実際に送信したリクエストと、テストがスタブした内容を比較します。
reticle_observe({ action: "network", sessionId, since })
テストでリクエストをアサートしているのにリクエストがない場合、テストスイートが検証したのはフィクスチャです。古くなったクライアントキャッシュも、確認できるリクエストがまったくない同じ失敗です。そのため TanStack Query の登録が重要です。キャッシュは唯一の証拠だからです。
3. UI は変化したが、状態は変化していない。 最も見つけにくい誤った成功であり、DOM やスクリーンショットによるチェックでは検出できません。
reticle_look({ action: "state", sessionId, store, path })
ストアに別の値が保持されているのに、ビューが1つの値を描画している場合、レンダーツリーからは分からないバグです。これが空を返す場合や hasCapabilities が false の場合は、ストアが登録されていません。その旨を伝えてください。登録されるまでは、上記の状態チェックはすべて無意味だからです。
4. 誰もレスポンスを読み取っていない。 アプリが一度も消費しなかった 2xx は、verified: "unknown" と verifiedReason: "outcome_unread" として表示されます。これは通常、実際のアプリのバグです。リクエストだけをアサートするテストなら、成功と判定してしまいます。
5. 誰もテストしていない画面全体。
reticle_run({ tool: "reticle_verify", sessionId, args: { action: "crawl" } }) // click sweep, returns anomalies
reticle_run({ tool: "reticle_verify", sessionId, args: { action: "coverage" } }) // { total, exercised, untouched }
crawl があるのは、(各コントロールをクリックして、コンソールエラーがないことをアサートする)手作業での簡易チェックそのものが、パターン1に当たるからです。
何を証拠とみなすか
誤った成功が確認されるのは、違和感があると感じたときではなく、アプリがテストと矛盾するときです。Reticle はこのケースを直接示します。verified: "no" と verifiedReason: "contradicted" は、あるチャネルが UI の主張と両立しない内容を観測したことを意味します。たとえば、画面が進んだのにリクエストが失敗した、シグナルが DOM と食い違った、誰も要求していない値をフィールドが返した、といった場合です。
unknown は誤った成功でも成功でもありません。Reticle が判定できなかったことを意味します。unknown として報告してください。
次に、アプリだけでなくテストも修正する
確認した誤った成功ごとに、それを見逃したテストは残ったままで、次も同じ失敗を見逃します。不在ではなく、アプリが生み出すべき結果(ステータス付きのリクエスト、シグナル、状態パス)を明示するアサーションに書き換えてください。判定を成功にするためにチェックを決して弱めないでください。 それが誤った成功を招いた原因です。
すべてのインデックスを1ページずつ確認するには、curl https://docs.reticle.sh/llms.txt を実行してください。Reticle が検出できなかった事例を見つけましたか? kind: "gap" を指定して reticle_session { action: "feedback" } を実行してください。これが何を作るかを決めるシグナルです。