agentic-tdd について
実行中のアプリにレッド・グリーン・リファクターのTDDを適用するReticle向けスキルです。操作前に期待する結果を定義し、保存したフローを回帰確認に再利用します。
主な機能
- 01操作前に期待結果をアサート
- 02シグナル、状態、ネットワーク、要素を確認
- 03実装後に同じアサーションを再実行
- 04フローを保存して回帰テストに再利用
活用シーン
- 01機能実装前にテストを作成
- 02動作を保つリファクタリングの検証
- 03エンドツーエンドの操作を回帰確認に変換
MCP 対応
Reticleは、このスキルが使う操作、アサーション、記録、検証のツールをMCP経由で提供します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ reticlehq/ reticle --skill agentic-tddインストール後、Claude Code で/agentic-tddを入力して読み込まれたか確認します。
詳細
赤・緑・リファクタリング:実行中のアプリに対して
ユニットテストはユニットを動かします。「Deploy をクリックすると /api/deploy に POST し、ストアが deploying に移行して、バナーが表示される」とは言えません。その結果が現れるのは、アプリ全体を実行したときだけだからです。そのため、興味深いバグが潜むまさにその地点でループが止まり、エージェントはコードを書いて期待するしかなくなります。
これは Reticle を使って実際のアプリを動かし、同じ手順を一段上のレベルで実行します。まだセットアップしていない場合は、reticle スキルに従ってください。Reticle をインストールし、init によるアプリのファイル変更前にユーザーに確認し、1 つのフローを実証します。
なぜこれは単なる事後テストではなく TDD なのか
テストファーストの価値は、まだ答えがわからないうちにオラクルを書くことにあります。結果を見たあとに書かれた期待値は、起きたことに合わせていつでも調整できます。エージェントは特に、その調整が得意です。今書いたコードが正しいといえるような出力の解釈を見つけてしまいます。
reticle_act_and_wait({ ref, action, until }) は順序を構造的に強制します。until はアクションの引数なので、その結果はアクションの実行前に明示されます。これは偽装できない形で実現した赤・緑のループです。
1. RED:期待値を書き、失敗を確認する
機能を書く前に、アプリが何をしなければならないかを明示します。
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "allOf", predicates: [
{ kind: "net", method: "POST", urlContains: "/api/deploy", status: 200 },
{ kind: "signal", name: "deploy:started" },
{ kind: "element", query: { testid: "deploy-banner" } },
{ kind: "console", level: "error", absent: true },
]}})
ここでは verified: "no" を期待します。確認していない赤は、信頼できないテストです。 何も書いていないのに yes が返ってきた場合、その期待値は変更内容に対して具体性が足りません。適切な理由で失敗するまで、条件を絞り込んでください。
verified: "unknown" は赤ではありません。Reticle が判定できなかったという意味なので、ループからシグナルがまったく得られません。コードを書く前にこれを解決してください。通常は、アプリが実際に生み出せる結果を指定します。
2. GREEN:同じ呼び出しがパスするまで実装する
条件を満たす最小限の変更を行い、その後、まったく変更せずに同じ呼び出しを再実行します。最後の言葉が重要です。作成したものに合わせて述語を編集すると、TDD は語りに変わってしまいます。アサーションを変更する必要がある場合は、元の期待値が誤っていた理由を声に出して説明してください。
判定が unknown / unsettled だった場合は、再度動作させるより、もう一度アサーションを実行するほうが望ましいです:reticle_assert({ predicate, since, timeout_ms: 8000 })。再実行すると、すでに発生した副作用が繰り返されます。
3. REFACTOR:期待値がセーフティネットになる
ここからは実装を自由に変更し、再実行します。述語はマークアップではなく動作(リクエスト、シグナル、状態のパス)に結び付いているため、動作を維持するリファクタリングなら引き続き成功します。一方、DOM の形状に依存するテストは、理由もなく失敗します。
4. 次の変更でもループを続ける
テストファーストで書く価値のあるジャーニーは、何度でも再実行する価値があります。一度保存しておきましょう:
reticle_run({ tool: "reticle_record", sessionId, args: { action: "start", name: "deploy" } })
// drive the journey with reticle_act_and_wait, as in step 1
reticle_run({ tool: "reticle_record", sessionId, args: { action: "stop", name: "deploy" } })
reticle_run({ tool: "reticle_flow_save", sessionId, args: { flowName: "deploy" } })
reticle_run({ tool: "reticle_verify", sessionId, args: { action: "flows" } }) // every saved flow, no model per flow
これにより、赤・緑のループが手書き不要のリグレッションテストスイートになります。
何をアサートするか:強い順
- アプリが自ら発するシグナル(
{ kind: "signal" }):アプリ自身の語彙で成功を宣言します。利用可能な中で最も強い方法です。 - 状態(
reticle_look { action: "state" }):アプリが認識している状態です。ストアが変わらないまま UI だけが変化した場合に検出できます。 - ネットワーク:リクエスト、メソッド、ステータスです。実際のものの代わりにモックが使われている場合に検出できます。
- 要素の表示:必要ですが、これだけでは不十分です。何でもレンダリングできます。
- コンソールエラーがないこと:常に含めますが、これだけに頼ってはいけません。不在だけを条件とする述語は、何にも接続されていないコントロールでもパスします。
誠実さ
判定を緑にするために、チェックを決して弱めないでください。 このループにおいて、それは些細な過ちではありません。ループを逆向きに回すことになり、動作しない機能を対象とした緑のテストスイートができあがります。
述語のリファレンス:curl https://docs.reticle.sh/predicates.md。その他すべて:curl https://docs.reticle.sh/llms.txt。