Skip to main content

test-driven-development

TDD(テスト駆動開発)を Red-Green-Refactor サイクルで実行し、C1カバレッジ100%を達成する。実装・テストは言語固有スキルに委譲する。「TDDで実装して」「テスト駆動で開発して」「TDDサイクルを回して」「テストファーストで作って」「カバレッジ100%で実装して」などのリクエストで必ずこのスキルを使う。

Source facts

Repository
ynitto/sandbox
Last source activity
September 19, 2026 at 00:45
Detected SKILL.md language
Japanese
Stars
1
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
7 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
test-driven-development
description
TDD(テスト駆動開発)を Red-Green-Refactor サイクルで実行し、C1カバレッジ100%を達成する。実装・テストは言語固有スキルに委譲する。「TDDで実装して」「テスト駆動で開発して」「TDDサイクルを回して」「テストファーストで作って」「カバレッジ100%で実装して」などのリクエストで必ずこのスキルを使う。
metadata
{"version":"1.1.0","tier":"stable","category":"implementation","tags":["tdd","red-green-refactor","coverage","behavior-testing","tracer-bullet"]}
# test-driven-development Red-Green-Refactor サイクルでTDDを実行し、C1カバレッジ100%を目指す。 実装とテストの作成は言語固有のスキルに従い、サイクル制御・テスト設計・カバレッジ分析を軸に進行する。 テストは**公開インターフェースを通じて「振る舞い」を検証**し、実装の詳細には依存しない。 1サイクルにつき「1テスト→1実装」の**垂直スライス**で進め、テストをまとめ書きしない。 --- ## 参照ファイル(段階的に読む) | 知りたいこと | 参照 | |---|---| | 良いテスト / 悪いテストの具体例 | [references/good-and-bad-tests.md](references/good-and-bad-tests.md) | | どこをモックすべきか・モックしやすい設計 | [references/mocking.md](references/mocking.md) | | テスタビリティの高いインターフェース設計 | [references/interface-design.md](references/interface-design.md) | | ディープモジュール(小さい入口・深い実装) | [references/deep-modules.md](references/deep-modules.md) | | リファクタリング候補の見極め | [references/refactoring.md](references/refactoring.md) | --- ## 鉄則 ### 1. テストファースト厳守 実装コードより先にテストを書く。例外なし。 「先に実装してからテストを追加する」は TDD ではない。 ### 2. スキル活用 実装コードの記述は実装スキルの手順に従い、テストコードの記述はテストスキルの手順に従う。 該当スキルが利用可能な場合は必ずその SKILL.md を読み込んで手順を適用する。 ### 3. 最小実装の原則 GREEN フェーズでは、テストを通すために必要な最小限のコードだけを書く。 将来の要件を先取りした実装は禁止。YAGNI を徹底する。 ### 4. 振る舞いをテストする(実装詳細ではない) テストは公開インターフェースを通して「何をするか(WHAT)」を検証する。 内部の協力オブジェクトをモックする、プライベートメソッドを叩く、呼び出し回数をアサートする、 DB を直接クエリして検証する――これらは禁止。実装をリファクタしてもテストが壊れない状態を保つ。 詳細と具体例は [references/good-and-bad-tests.md](references/good-and-bad-tests.md)。 ### 5. 垂直スライス厳守(水平スライス禁止) 「全テストを先に書いてから全実装を書く」(=水平スライス)は禁止。 これは*想像上*の振る舞いをまとめてテストすることになり、データ構造や関数シグネチャの「形」を テストする壊れやすいテストを生む。 **正しい進め方**: 1テスト→1実装→次、の垂直スライス。各サイクルは前のサイクルで分かったことに 応答する。書いたばかりのコードだからこそ、何をどう検証すべきかが分かる。 ``` WRONG(水平): RED: test1, test2, test3, test4, test5 GREEN: impl1, impl2, impl3, impl4, impl5 RIGHT(垂直): RED→GREEN: test1→impl1 RED→GREEN: test2→impl2 ... ``` --- ## パス解決 このSKILL.mdが置かれているディレクトリを `SKILL_DIR`、その親ディレクトリを `SKILLS_DIR` とする。他スキルは名前で検索する: `${SKILLS_DIR}/[skill-name]/SKILL.md` を優先し、見つからなければ利用可能なスキルディレクトリを横断して探すこと。 --- ## スキルペアの解決 Phase 0 で対象の言語・フレームワークを特定したら、利用可能なスキルから **実装スキル** と **テストスキル** のペアを自由に判断して決定する。 - 実装・テスト用途に合致するスキルが見つかればその SKILL.md を読み込んで手順に従う - 合致するスキルがなければ、言語の標準的なテストフレームワーク(TypeScript: vitest/jest、Python: pytest、Go: testing パッケージ、Java: JUnit、Rust: cargo test)を使い実装する - ユーザーが特定のスキルを指定した場合はそれに従う --- ## カバレッジツールの設定 C1(分岐カバレッジ)を計測するために、言語に応じたツールを使用する。 | 言語 | ツール | 分岐カバレッジオプション | |------|--------|-------------------------| | TypeScript/JavaScript | vitest / jest + istanbul | `--coverage --coverageReporters=json-summary` | | Python | pytest-cov | `--cov --cov-branch --cov-report=json` | | Go | go test | `-coverprofile=cover.out -covermode=count` | | Java | JaCoCo | 分岐カバレッジはデフォルトで計測 | | Rust | cargo-tarpaulin / llvm-cov | `--branch` | | C# (.NET) | coverlet | `--collect:"XPlat Code Coverage"` | Phase 0 でカバレッジ計測が動作することを確認してからサイクルに入る。 --- ## フェーズ実行手順 ### Phase 0: セットアップ 1. **対象の特定** - 実装対象の機能・要件を確認する - 言語・フレームワークを特定する - 既存コードがあれば構造を把握する 2. **スキルペアの決定** - 利用可能なスキル一覧を確認する - 実装スキルとテストスキルのペアを決定する 3. **カバレッジ環境の確認** - カバレッジツールがインストール済みか確認する - 未導入なら導入する(例: `npm install --save-dev @vitest/coverage-v8`、`pip install pytest-cov`) - カバレッジ計測コマンド(例: `npx vitest run --coverage`、`pytest --cov --cov-branch`)を実行し、動作を確認する - 失敗した場合は原因(設定ファイル不備・ツール未導入など)を特定して解消してから次のステップへ進む 4. **インターフェースと振る舞いの計画** - 公開インターフェースがどうあるべきかをユーザーに確認する(「公開 API はどんな形が良いか?」) - テストすべき**振る舞い**を列挙する(実装手順ではない)。優先度を付ける - **すべてをテストはできない。** どの振る舞いが最も重要かをユーザーに確認し、 クリティカルパスと複雑なロジックにテスト労力を集中する - テスタビリティを設計に織り込む: 依存は受け取る・副作用より戻り値・小さい表面積 ([references/interface-design.md](references/interface-design.md))。 小さい入口に複雑さを隠す[ディープモジュール](references/deep-modules.md)の機会を探す - コードベース探索時は、プロジェクトの用語集(ドメイングロッサリ)に合わせてテスト名・ インターフェース語彙を選び、該当領域の ADR を尊重する 5. **機能の分解** - 実装対象を、テスト可能な小さい単位(インクリメント)に分割する - 依存順に並べる(依存先を先に実装する) - 各インクリメントに期待動作(=検証する振る舞い)を明記する **ゲート条件:** スキルペア決定済み、カバレッジ計測動作確認済み、テスト対象の振る舞い合意済み、インクリメント一覧作成済み --- ### Phase 1~N: TDDサイクル(インクリメントごとに繰り返す) 各インクリメントについて、以下の Red-Green-Refactor サイクルを実行する。 **最初のサイクルはトレーサーバレット**: 最も重要な振る舞いについて「1つのことを確認する」 テストを1本だけ書き、最小実装で通す。これでパスがエンドツーエンドで通ることを証明してから、 残りの振る舞いを1つずつ積み上げる。 #### Step 1: RED — 失敗するテストを書く **テストスキル** の手順に従い、以下の方針でテストを書く: - **一度に1つの振る舞い**だけをテストする。まとめ書きしない(鉄則5) - 公開インターフェースを通して観測可能な振る舞いを検証する(実装詳細に触れない、鉄則4) - テストは具体的な入力と期待出力を含む。テスト名は WHAT を表す - 正常系・境界値・異常系は、それぞれ別の RED→GREEN サイクルとして1つずつ積み上げる (1サイクルにまとめて網羅しようとしない) - モックはシステム境界(外部 API・DB・時刻/乱数・FS)のみ。内部はモックしない ([references/mocking.md](references/mocking.md)) テスト作成後、テストを実行して **失敗することを確認する**。 テストが失敗しない場合は、テストの内容を見直す(既に実装済みの機能をテストしている可能性がある)。 #### Step 2: GREEN — 最小限の実装を書く **実装スキル** の手順に従い、以下の方針で実装する: - Step 1 で書いたテストをすべてパスする最小限のコードを書く - 既存のテストも壊さない - 将来の要件は考慮しない(今のテストを通すことだけに集中する) 実装後、すべてのテストを実行して **パスすることを確認する**。 テストが失敗する場合は、実装を修正する(テストは変更しない)。 #### Step 3: REFACTOR — リファクタリング テストがすべてパスしている状態(GREEN)で、以下を検討する: - コードの重複排除(関数・クラスの抽出) - 命名の改善 - 関数・メソッドの分割(テストは公開インターフェースに残す) - シャローモジュールを[ディープモジュール](references/deep-modules.md)に(複雑さを小さい入口の内側へ) - 自然な箇所への SOLID 原則の適用 - 新しいコードが明らかにした既存コードの問題 候補の見極めは [references/refactoring.md](references/refactoring.md) を参照。 **RED 中はリファクタしない。** 必ず GREEN にしてから行い、各ステップ後にテストを実行する。 リファクタリング後、すべてのテストが引き続きパスすることを確認する。不要であればスキップしてよい。 #### サイクル完了チェック 各サイクル末尾で以下を出力する: ``` === TDD Cycle [N] 完了 === インクリメント: [名前] テスト数: [追加数] / [累計] テスト結果: ALL PASSED / [失敗数] FAILED 次のインクリメント: [名前] or なし ``` --- ### Phase C: カバレッジギャップ分析 全インクリメントのTDDサイクル完了後(または途中でも定期的に)、カバレッジを計測する。 1. **カバレッジ計測を実行** - 言語に応じたカバレッジコマンドを実行する - JSON形式のレポートを取得する 2. **C1カバレッジを確認** - 分岐カバレッジ(branch coverage)の数値を確認する - 100%未満の場合、未カバーの分岐を特定する 3. **未カバー分岐の分析** - カバレッジレポートからカバーされていない行・分岐を特定する - 各未カバー分岐について、どのような入力・条件でその分岐を通るか分析する - 追加すべきテストケースを一覧化する 4. **追加サイクルの実行** - 未カバー分岐に対して RED → GREEN → REFACTOR サイクルを追加実行する - この場合の RED は、未カバー分岐を通すテストケースの追加 - GREEN は分岐を正しく処理する実装の追加(必要な場合のみ) 5. **再計測** - カバレッジを再計測し、C1 100%に到達したか確認する **反復制限:** カバレッジギャップ分析は最大 5 回まで繰り返す。 5回でC1 100%に到達しない場合、残りの未カバー分岐をユーザーに報告し、 対応方針を相談する(テスト困難なコード構造の改善が必要な可能性がある)。 各回で以下を出力する: ``` === Coverage Analysis [M回目] === C1 カバレッジ: [数値]% 未カバー分岐: [件数] 対象ファイル: [ファイル一覧] 次のアクション: 追加テスト作成 / C1 100% 達成 / ユーザーに相談 ``` --- ### Phase F: 最終確認 1. **全テスト実行** — すべてパスすることを確認 2. **カバレッジ最終計測** — C1 100%であることを確認 3. **完了レポートを出力** ``` === TDD 完了レポート === 対象機能: [機能名] 実行サイクル数: [N] カバレッジ分析回数: [M] 最終 C1 カバレッジ: [数値]% テスト総数: [N] 全テスト結果: ALL PASSED 使用スキル: 実装: [スキル名] テスト: [スキル名] ``` --- ## 各ステップで意識すべきコンテキスト ### テスト作成時(RED / カバレッジギャップ) - 対象インクリメントの期待動作 - 既存のテストファイルのパス(追記先) - 既存の実装コードのパス(テスト対象) - テストフレームワークの種類 - RED フェーズでは、テストは現時点で失敗する想定であること - カバレッジギャップ分析では、未カバー分岐の該当行・条件を把握した上でテストを追加すること ### 実装時(GREEN) - パスすべきテストの内容(テストコードのパスまたは内容) - 既存の実装ファイルのパス - テストをパスする最小限の実装を書くこと - 既存のテストを壊さないこと --- ## エラーリカバリー | 状況 | 対処 | |------|------| | テストランナーの実行エラー | コマンドを 1 回リトライ。失敗時はフレームワーク設定をユーザーに確認 | | RED フェーズでテストが通ってしまう | テストが実装に先行しているか確認。実装を一時的に削除してテストを RED にする | | GREEN フェーズで 3 回修正してもパスしない | テスト自体の妥当性を再評価。テストが誤っていれば修正し、設計上の問題なら再設計を提案 | | カバレッジツールのパース失敗 | カバレッジレポートを手動解釈し、未カバー箇所を特定してテストを追加 | | REFACTOR でテストが失敗 | リファクタリングを元に戻し、GREEN 状態に復帰してから再試行 | | 20 サイクル超過 | ユーザーに報告。機能分割・スキップ・手動継続の選択肢を提示 | --- ## 制約とガードレール - **TDDサイクル上限:** 1機能につき最大 20 サイクル。超過時はユーザーに報告する - **カバレッジ分析上限:** 最大 5 回 - **テスト実行失敗時のリトライ:** GREEN フェーズで 3 回実装を修正してもテストがパスしない場合、テスト自体の妥当性を再評価する - **リファクタリングでテスト失敗:** リファクタリングを元に戻し、テストがパスする状態に復帰してから再試行する
View on GitHub