mcpField
T
test-driven-development

test-driven-development

github.com/christopher-bussテスト・品質857 回インストール3 週間前に更新
リポジトリ

test-driven-development について

test-driven-developmentは、ソフトウェア開発者向けのテスト駆動開発スキルです。公開インターフェースを通じて振る舞いを検証し、テストと実装を一つずつ進めてからリファクタリングします。

主な機能

  1. 01公開インターフェース経由の振る舞い検証
  2. 02一件ずつ進めるレッド・グリーンサイクル
  3. 03インテグレーション形式のテストを重視
  4. 04インターフェースとテスト計画の事前確認
  5. 05テスト成功後のリファクタリング

活用シーン

  1. 01新機能で重要な振る舞いをテスト計画
  2. 02機能を段階的に実装して検証
  3. 03テストの内部実装への依存を確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/christopher-buss/skills --skill test-driven-development

インストール後、Claude Code で/test-driven-developmentを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
deep-modules.md
interface-design.md
mocking.md
refactoring.md
tests.md

詳細

テスト駆動開発

考え方

基本原則:テストでは、実装の詳細ではなく、公開インターフェースを通じて振る舞いを検証します。コードは全面的に変更してもかまいませんが、テストは変更されるべきではありません。

良いテストは、実際のコードパスを公開 API 経由で実行する、統合テスト形式のものです。システムが「どのように」動作するかではなく、「何を」するかを記述します。良いテストは仕様書のように読めます。「有効なカートでユーザーがチェックアウトできる」とあれば、どのような機能があるかが正確に伝わります。内部構造を気にしないため、こうしたテストはリファクタリング後も機能します。

悪いテストは実装と密結合しています。内部の協力コンポーネントをモックしたり、プライベートメソッドをテストしたり、外部の手段(インターフェースではなくデータベースを直接クエリするなど)で検証したりします。警告サインは、リファクタリングで振る舞いが変わっていないのにテストが失敗することです。内部関数の名前を変えただけでテストが失敗するなら、そのテストは振る舞いではなく実装をテストしていたことになります。

例はtests.mdを、モックのガイドラインはmocking.mdを参照してください。

アンチパターン:水平スライス

テストをすべて先に書いてから、実装をすべて書くのはやめてください。 これは「水平スライス」です。RED を「テストをすべて書くこと」、GREEN を「コードをすべて書くこと」と捉えています。

これでは質の悪いテストが生まれます。

  • まとめて書かれたテストは、_実際の_振る舞いではなく、_想像上の_振る舞いをテストします
  • ユーザーに見える振る舞いではなく、物事の_形_(データ構造や関数シグネチャ)をテストすることになります
  • テストは実際の変更に対して鈍感になり、振る舞いが壊れても成功し、振る舞いに問題がなくても失敗するようになります
  • 実装を理解する前にテストの構造を確定してしまい、見通しが追いつかなくなります

正しいアプローチ:トレーサー弾による垂直スライスです。テストを1つ書き、実装を1つ行い、それを繰り返します。各テストは、前のサイクルで学んだことを反映します。コードを書いたばかりなので、どの振る舞いが重要で、どう検証すればよいかを正確に把握できます。

WRONG (horizontal):
  RED:   test1, test2, test3, test4, test5
  GREEN: impl1, impl2, impl3, impl4, impl5

RIGHT (vertical):
  RED→GREEN: test1→impl1
  RED→GREEN: test2→impl2
  RED→GREEN: test3→impl3
  ...

ワークフロー

1. 計画

コードを書く前に、次のことを行います。

  • 必要なインターフェースの変更についてユーザーに確認する
  • テストする振る舞いについてユーザーに確認する(優先順位を付ける)
  • ディープモジュール(小さなインターフェース、深い実装)の機会を見つける
  • テスト容易性を考慮してインターフェースを設計する
  • 実装の手順ではなく、テストする振る舞いを列挙する
  • 計画についてユーザーの承認を得る

次のように尋ねます。「公開インターフェースはどのような形にすべきですか?テストで最も重視する振る舞いは何ですか?」

すべてをテストすることはできません。 最も重要な振る舞いをユーザーに確認します。あらゆるエッジケースをテストするのではなく、重要な経路と複雑なロジックにテストの労力を集中させます。

コードを書く前に、実装なしで test.todo を使ってテストの説明を記述したテストファイルを用意し、カバレッジについてユーザーのフィードバックを得ます。

2. トレーサー弾

システムについて1つのことを確認するテストを1つ書きます。

RED:   Write test for first behavior → test fails
GREEN: Write minimal code to pass → test passes
COMMIT: Commit this working test and code

これがトレーサー弾です。エンドツーエンドで経路が機能することを証明します。

3. 段階的なループ

残りの振る舞いについて、次の手順を繰り返します。

RED:   Write next test → fails
GREEN: Minimal code to pass → passes
COMMIT: Commit this working test and code

ルール:

  • テストは一度に1つ
  • 現在のテストに合格するために必要なだけのコードを書く
  • 将来のテストの振る舞いを先読みしない
  • 観察可能な振る舞いにテストを集中させる
  • コミット履歴で、振る舞いが追加される過程が明確にわかるようにする
4. リファクタリング

すべてのテストに合格したら、リファクタリング候補を探します。

  • 重複を抽出する
  • モジュールを深化させる(複雑さをシンプルなインターフェースの背後に移す)
  • 新しいコードによって既存のコードについて何が明らかになるか検討する
  • リファクタリングの各手順の後にテストを実行する

RED の間は決してリファクタリングしないでください。 まず GREEN にします。

サイクルごとのチェックリスト

[ ] Test describes behavior, not implementation
[ ] Test uses public interface only
[ ] Test would survive internal refactor
[ ] Code is minimal for this test
[ ] No speculative features added
[ ] Commit has been made with working test and code

コメント