Communitygithub.com

テスト駆動開発

テスト駆動開発(TDD)の原理とワークフローを説明し、公開インターフェースを通した動作検証と垂直スライス開発を推奨するスキルです。

テスト駆動開発 とは?

このスキルは、テスト駆動開発(TDD)の実践ガイドを提供します。コアの考え方は「テストは実装詳細ではなく公開インターフェースを通して動作を検証する」というもので、結合度の高い悪いテストパターンを避け、動作仕様として読み取れる良いテストを書くことを促します。特に「全テストを先に書き、後で全実装を行う」という水平スライスをアンチパターンとして警告し、1つのテスト→1つの実装を繰り返す垂直スライス(トレーサーブレット方式)を推奨しています。ワークフローは計画(ユーザーとの動作確認、優先順位付け)、トレーサーブレット(最初のテスト→最小限の実装)、インクリメンタルループ(1テストずつ追加)、リファクタリング(グリーン状態でのみ実施)の4段階で構成され、各サイクルでチェックリストを使った自己確認を行います。このスキールはClaude Code、Cursor、CodexなどのAIエージェントツールで利用可能で、SKILL.mdファイルとして読み込まれ、テスト駆動開発の規律を維持しながら段階的に開発を進めるための支援を行います。

対応~Claude Code~Codex CLI~Cursor
npx skills add madnpc/skills

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

テスト駆動開発 は何をしますか?

出力言語

デフォルトでは日本語(簡体字)を使用してユーザーとコミュニケーションし、テスト戦略、テスト説明、実装サマリーを日本語で記述します。ユーザーが明示的に他の言語を指定した場合や、既存のドキュメントの言語に別の取り決めがある場合は、その取り決めに従います。コード、コマンド、製品名、および原文を保持する必要がある引用は無理に翻訳しません。

Philosophy(基本哲学)

中核原理: テストは実装詳細ではなく、公開インターフェースを通して動作を検証すべきです。コードは完全に変更される可能性がありますが、テストは変更されるべきではありません。

良いテストは統合スタイルです。公開APIを通じて実際のコードパスを実行します。システムが 何をするのか を記述し、 どのようにするのか は記述しません。良いテストは仕様のように読めます。「ユーザーは有効なカートでチェックアウトできる」というテストは、どのような機能が存在するかを正確に示します。これらのテストは内部構造を気にしないため、リファクタリング後も耐えます。

悪いテストは実装に結合しています。内部のコラボレーターをモックしたり、プライベートメソッドをテストしたり、外部手段(データベースに直接クエリを実行するなど、インターフェースを使わない方法)で検証します。警告サイン:リファクタリングしても動作が変わっていないのにテストが壊れる場合。内部関数の名前を変更しただけでテストが失敗するなら、そのテストは動作ではなく実装をテストしています。

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

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

すべてのテストを先に書き、その後で全実装を行ってはいけません。 これは「水平スライス」であり、REDフェーズを「全テストを書く」、GREENフェーズを「全コードを書く」と捉える誤った方法です。

これは 質の低いテスト を生み出します:

  • 一括で書かれたテストは 実際の 動作ではなく 想像上の 動作をテストする
  • ユーザー向けの動作ではなく、データ構造や関数シグネチャなど 物の形 をテストすることになる
  • テストは実際の変更に対して鈍感になる。動作が壊れてもテストがパスし、動作が正しくてもテストが失敗する
  • 実装を理解する前にテスト構造にコミットしてしまい、視野が狭くなる

正しいアプローチ: トレーサーブレットによる垂直スライス。1テスト→1実装→繰り返し。各テストは前のサイクルで学んだことに基づいて書かれます。コードを書いたばかりなので、どの動作が重要でどのように検証すべきかが正確にわかります。

誤り(水平):
  RED:   test1, test2, test3, test4, test5
  GREEN: impl1, impl2, impl3, impl4, impl5

正しい(垂直):
  RED→GREEN: test1→impl1
  RED→GREEN: test2→impl2
  RED→GREEN: test3→impl3
  ...

ワークフロー

1. 計画

コードベースを探索する際には、CONTEXT.md(存在する場合)を読んで、テスト名とインターフェース用語がプロジェクトのドメイン言語と一致するようにし、触れる領域のADRも尊重します。

コードを書く前に:

  • 必要なインターフェース変更についてユーザーと確認する
  • テストすべき動作についてユーザーと確認する(優先順位付け)
  • インターフェース境界が不明瞭な場合、コードベース設計原則を用いて深いモジュールの機会を特定する。ユーザーが明示的に要求しない限り、別のスキルを自動的に呼び出さない。
  • テストする動作をリストアップする(実装手順ではなく)
  • 計画についてユーザーの承認を得る

質問例:「公開インターフェースはどのようにすべきですか?テストする上で最も重要な動作はどれですか?」

すべてをテストすることはできません。 ユーザーと正確にどの動作が最も重要かを確認してください。すべてのエッジケースではなく、クリティカルパスと複雑なロジックにテストの労力を集中させてください。

2. トレーサーブレット

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

RED:   最初の動作のテストを書く → テスト失敗
GREEN: パスする最小限のコードを書く → テスト成功

これがトレーサーブレットです。エンドツーエンドでパスが機能することを証明します。

3. インクリメンタルループ

残りの各動作に対して:

RED:   次のテストを書く → 失敗
GREEN: パスする最小限のコード → 成功

ルール:

  • 一度に1テストずつ
  • 現在のテストにパスするコードだけを書く
  • 将来のテストを先取りしない
  • テストは観測可能な動作に集中させる

4. リファクタリング

すべてのテストがパスしたら、リファクタリング候補 を探します:

  • 重複の抽出
  • モジュールの深化(複雑さをシンプルなインターフェースの背後に移動)
  • SOLID原則を自然な形で適用
  • 新しいコードが既存コードについて何を明らかにするかを検討
  • リファクタリングの各ステップ後にテストを実行

RED状態ではリファクタリングしないでください。 必ず先にGREENにしてください。

各サイクルのチェックリスト

[ ] テストは動作を記述しており、実装を記述していない
[ ] テストは公開インターフェースのみを使用している
[ ] テストは内部リファクタリング後も生き残る
[ ] コードはこのテストに対して最小限である
[ ] 推測による機能追加がない

関連スキル