tdd について
tdd は、小さな動作変更ごとにテストを先に書く開発スキルです。失敗ケースや観察可能な動作を確認しながら、段階的に変更やリファクタリングを進めるコーディング作業に適しています。
主な機能
- 01最初に失敗ケースを用意
- 02可逆な小さな単位で進行
- 03テスト成功後にリファクタリング
- 04観察可能な動作を検証
- 05変更と検証結果を報告
活用シーン
- 01失敗テストを基に動作を修正
- 02変更前にレガシーコードの動作を確認
- 03テスト成功を保ちながらリファクタリング
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ robsonrung/ rar-skills --skill tddインストール後、Claude Code で/tddを入力して読み込まれたか確認します。
詳細
TDD — テストファーストの実行
モデルを選ぶ前にブランチを選択します。コーディネーターの作業と決定論的なコマンドは、呼び出し権限の範囲内で実行します。この手法は現在のロールに適用します。ワーカーにはディスパッチしません。ワーカーをディスパッチする場合は、shared/references/model-preview.md と、そこで承認されているルートスナップショットを1つ使用します。ネストされたスキルやランナーはそれを使用し、再選択やワーカーのディスパッチは行いません。
鉄則
要求された動作を修正する前に、失敗する動作テストを用意します。 同じコードに同じ欠陥があることを証明できるなら、記録済みの失敗を再利用します。
- 既存の有効な作業を保持します。履歴の順序を変えることだけを目的に、コードを削除して作り直してはいけません。
- 新しいテストが成功する場合、既存の動作を特定できることがあります。しかし、それは欠けている動作を示すものでも、テストが誤っていることを証明するものでもありません。関連する失敗、または制御された反例を使って、そのテストが何を検出するのかを確認します。
ステップ0 — このコードは誰のものか?
テストされていないレガシーコードにリスクの高い変更を加える場合、欠けている特性評価には safe-incremental-coding を適用します。変更対象の範囲をカバーする既存の動作と失敗の証拠を再利用します。その保護がすでにある場合は、直接進めます。
ループ
動作を1つ増やすごとに、ループを1回実行します。各パスは、ためらいなく破棄できるほど小さく保ちます。
- 最小の可逆的な変更を定めます。 呼び出し元から見える動作を1つだけ増やします。自然に感じるよりも小さく、学びを得るための最も低コストで可逆的な一歩にします。結果を一文で述べられないなら、そのステップは大きすぎます。分割します。選ぶときに、こう言います。「ここでの最小の可逆的な変更は…です」。
- 先にテストを書き、失敗を予測して、実際に失敗することを確認します。 呼び出し元の視点から、コードが何をすべきかを表現します。実行前に予想される失敗を声に出して確認します。予想とは異なる失敗が起きても、そこからすでに学びを得ています。
- 最も簡単な方法でグリーンにします。 合格する最小限のコードを書きます。素朴な実装でかまいません。これは戦術的なステップであり、設計のステップではありません。まだ磨き込まないでください。
- グリーンの状態でリファクタリングします。 具体的な設計上の問題を改善し、次の動作変更に進む前に、影響を受けるテストを実行します。臭いがある場合は
clean-codeを適用して、その臭いに名前を付けます。必ず成立すべき内部不変条件はアサートします。アサーションは実行可能なドキュメントであり、失敗は捕捉して無視すべき条件ではなく、バグです。 - 整合性のある変更を統合します。 各変更は小さく、テストに合格する状態を保ちます。ユーザーまたは呼び出し元から承認された場合に限りコミットします。コミットの区切りはタイマーではなく、完了した動作と合格したチェックを基準に選びます。
変数を制御する
ステップの効果を特定できて初めて、そのステップから学べます。
- 変更は一度に1つだけにします。 リファクタリングと動作変更、設定の調整を決してまとめてはいけません。
- 間欠的に失敗するテストは失敗であり、再実行して合格にしてはいけません。
- 偶然に頼ったプログラミングは避けます。コードが合格したら、その理由を把握します。
- チェックを不正に通してはいけません。 テストを削除、スキップ、弱体化、範囲縮小、またはモックで無効化してグリーンにすることは禁止です。修正権限の範囲内で、テスト実装に誤りがあると証明できた場合は、その誤りを修正します。受け入れ済みのプロダクト契約を変更するには、判断が必要です(
shared/references/engineering-rules.md、Contract integrity)。
テスト作成の基準
作成時のルールです。既存のテストに価値があるか疑問がある場合は、test-lens が判断します。以下は、指摘を受けずに済むようにテストを書く際の基準です。
- スタイルの優先順位:出力ベース(純粋関数の戻り値をアサートする)>状態ベース>通信ベース(モック)。コードは、関数型コア(純粋な判断)を可変シェル(薄い I/O の接着層)で包むことで、出力ベースに近づけます。
- 観測可能な振る舞いをアサートし、実装の詳細は決してアサートしません。スタブへの呼び出しは決してアサートしません。
- AAA — Arrange / Act / Assert をそれぞれ 1 つ — 振る舞いを示すドメインの文として命名します。
testIsValid_case3ではなく、delivery_with_a_past_date_is_invalidのようにします。 - 書きにくいテストは設計上の問題を示しています。テストではなく、設計を直します。
- リファクタリングの判定基準:実装をまったく別のものに差し替えた場合も、このテストは有効でしょうか? 有効であるべきです。
設計とリスクの手がかり
テストやリファクタリングを選ぶ際は、以下の手がかりを使います。統合のたびに別のレビュー工程を設ける必要はありません。
- Farley の 5 つのレバー:モジュール性、凝集性、関心の分離、抽象化、低結合。変更範囲内で、これらの特性に対する回帰に対処します。
- 「もし……だったら?」:無効な入力、依存関係の障害、並行処理、セキュリティ、金銭的損失など、この振る舞いによって明らかになる障害ケースを選びます。受け入れ条件にすでに含まれているケースや判断を再利用します。
ステップごとの出力契約
各ループの反復(またはまとまりのあるバッチ)の後に、以下を報告します。
changed:編集した内容。behavior:コードが新たに実行するようになった振る舞い、または維持された振る舞い。risk_guarded:このステップのテストが主に防ぐ設計上またはデータ上のリスク。verification:実行したテストやチェック、または実行できなかった理由。
振り分け
- 保存状態、キュー、再試行、マイグレーション、外部 API → 承認済みの data-systems-coding-lens の所見を再利用します。レンズを実行するのは、未対応のデータリスクや設計面の変更がある場合に限り、ループの反復ごとには実行しません。
- リファクタリングのステップでは、においの用語や命名に
clean-codeを適用します。 - 既存のテストを残す価値があるか判断するときは、
test-lensを適用します。 - ループの途中で原因不明の失敗が表面化した場合は、
diagnoseを適用します。原因が分かっている失敗や回帰は現在のループ内で対処し、2 回目の調査を始めずに既存の証拠を利用します。
注意点
- 巨大なステップ — 最初のテスト実行まで半日かかるほどコードを書いてしまうこと。
- テストを後から書く — 既存のコードに合わせたテストでは、意図した振る舞いを見落とすことがあります。受け入れ条件や関連する反例に照らして確認し、有効な作業は維持します。
- カバレッジの追求 — カバレッジはループの副産物であり、目標ではありません。
- テストが通った後の過剰な作り込み — 安全でない状態で設計することです。設計はリファクタリングのステップで行います。
- 「テストする時間がない」 — 速度と品質の間にトレードオフはありません。手戻りを減らすことが、より速く進む方法です。
- 関係のないコードを整理するために、スコープを広げないでください。
- すっきり見えるという理由だけで、レイヤー、サービス、ヘルパーを追加しないでください。
- 解決策によって明瞭さよりも間接性が増す場合は、問題のない局所的な結合を弱めないでください。
- 設計の方向転換が必要なときは、小さなリファクタリングのステップを重ねて、テストが通る状態からテストが通る状態へと進めます。考えを変えるにはコストがかかります。そのコストを抑えられるのは、先に小さなステップを重ねていたからです。
- このスキルが要約した書籍の原文を引用したり、再構成したりしないでください。