common-test-driven-development について
common-test-driven-developmentは、コードの追加や変更にテスト駆動開発を適用するスキルです。失敗するテストから始め、最小限の実装を行い、リファクタリング後にも検証する手順を示します。
主な機能
- 01既存テストの確認と実行
- 02失敗するテストを先に作成
- 03最小限の実装でテストを通過
- 04テストを保ちながらリファクタリング
- 05関連する境界値とエラーの検証
- 06関連テストスイートの実行
活用シーン
- 01新しい関数やモジュールのテスト
- 02不具合の再現と修正
- 03業務ロジックのリファクタリングと回帰確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ xip-online-applications/ skills --skill common-test-driven-developmentインストール後、Claude Code で/common-test-driven-developmentを入力して読み込まれたか確認します。
詳細
common-test-driven-development
正しさを確保し、デグレードを防ぐため、テスト駆動開発のアプローチに従い、実装コードの前または実装と並行してユニットテストを作成します。
使用する場面
次の場合にこのスキルを使用します。
- 新しい関数、クラス、メソッド、モジュールを作成するとき
- 既存のビジネスロジックや動作を変更するとき
- バグを修正するとき(まず、バグを再現する失敗するテストを作成します)
- コードをリファクタリングするとき(変更の前後でテストが存在し、成功することを確認します)
- ユーザーから機能やロジックの実装を依頼されたとき
手順
-
まず既存のテストを確認します。 実装コードを書く前に、変更しようとしているコードに関連するテストファイルがコードベースにないか検索します。
*.test.*、*.spec.*、*_test.*、test_*.*などのパターンに一致するファイルや、tests//__tests__/ディレクトリを探します。- 既存のテストが見つかった場合は実行します。成功する場合はそのまま維持し、意図的な動作変更によってアサーションが無効にならない限り、成功しているテストを変更しないでください。
- 新しい要件と矛盾する古い動作をアサーションが反映しているために既存のテストが失敗する場合は、該当するアサーションだけを更新します。テスト全体を削除したり、書き直したりしないでください。
-
まず、シンプルな失敗するテストを1つ作成します。 ロジックを実装する前に、次の作業を行います。
- 期待する動作を表す、可能な限り小さなユニットテストを作成します。
- テストは実行可能で、実装がまだない、または新しい要件を満たしていないことを理由に失敗する必要があります(レッドフェーズ)。
- 確認する動作が分かる明確な名前をテストにつけます(例:
it should return the sum of two numbers、test_empty_list_returns_none)。 - 一度に複数のテストを書かないでください。まず1つから始めます。
-
最小限の実装でテストを成功させます。 失敗するテストを成功させるために必要な本番コードだけを書きます(グリーンフェーズ)。
- テストでまだ求められていない機能を追加しないでください。
- この段階では過剰な設計や、将来の要件の先取りを避けてください。
- テストを実行し、成功することを確認します。
-
テストを成功させたままリファクタリングします。 テストが成功したら、次の作業を行います。
- 動作を変えずに、コードの構造、命名、重複を改善します。
- リファクタリング後に関連するテストをすべて実行し、問題がないことを確認します。
-
追加の動作について繰り返します。 動作を追加するたびに、次の作業を行います。
- 新しい失敗するテストを1つ作成します。
- 変更を最小限に抑えてテストを成功させます。
- 必要に応じてリファクタリングします。
- 要件をすべて満たすまで続けます。
-
テスト品質のルール。
- 各テストで確認する動作やシナリオは1つだけにします。
- テストは互いに独立させます。可変状態の共有や実行順序への依存を避けてください。
- 仕様として読める、分かりやすいテスト名をつけます。
- 内部実装の詳細よりも、公開インターフェースのテストを優先します。
- すべてをモック化しないでください。外部依存(I/O、ネットワーク、データベース、クロック)のみをモック化します。
- テストは高速に保ちます。ユニットテストをネットワーク、ファイルシステム、データベースに依存させないでください。
-
テストの構成。 Arrange-Act-Assert(AAA)または Given-When-Then パターンに従います。
- Arrange/Given:入力と依存関係を準備します。
- Act/When:テスト対象の単位を呼び出します。
- Assert/Then:出力や副作用を検証します。
-
エッジケース。 正常系のテストが成功したら、次のテストを追加します。
- 境界値(空のコレクション、ゼロ、null/undefined、最大値)。
- エラー条件(無効な入力、データの欠落、例外)。
- 実装するロジックに関係するエッジケースだけを追加します。
-
関連するテストスイート全体を実行します。 すべての変更が完了したら、影響を受けるモジュールまたはパッケージのテストスイート全体を実行し、デグレードがないことを確認します。
-
時間を節約するためにテストを省略してはいけません。 コードを作成するなら、テストも作成します。対応するテストなしで本番コードを書くことが許される状況はありません。時間が限られている場合はスコープを縮小しますが、実装した範囲のすべての行をテストでカバーしてください。
例
シンプルな関数の TDD サイクル
Step 1 — Write failing test:
test("adds two positive numbers", () => {
expect(add(2, 3)).toBe(5);
});
Step 2 — Minimal implementation:
function add(a, b) {
return a + b;
}
Step 3 — Test passes. Refactor if needed (nothing to refactor here).
Step 4 — Next test:
test("returns 0 when both arguments are 0", () => {
expect(add(0, 0)).toBe(0);
});
Step 5 — Already passes. Move to next behavior.
Handling existing tests
Scenario: You need to change a function's return type from number to string.
1. Run existing tests — they pass.
2. Identify which assertions will break due to the intentional change.
3. Update ONLY those assertions to expect the new string return type.
4. Confirm updated tests fail (since implementation hasn't changed yet).
5. Change the implementation.
6. Confirm all tests pass.