test-coverage について
test-coverage は、未テストの分岐、エラー経路、境界条件を対象に単体テストを増やすスキルです。カバレッジの基準値を測定し、検出した技術スタックに応じたテスト作成と検証を進め、変更やコミットの範囲も制御します。
主な機能
- 01技術スタックとテストフレームワークの検出
- 02カバレッジ基準値の測定
- 03分岐や境界条件の不足箇所の特定
- 04単体テストの作成と自己点検
- 05カバレッジ向上と安定性の検証
活用シーン
- 01CI のカバレッジ不足への対応
- 02エラー経路のテスト追加
- 03リリース前のテスト不足確認
- 04コードレビューで見つかった不足の補完
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ luongnv89/ skills --skill test-coverageインストール後、Claude Code で/test-coverageを入力して読み込まれたか確認します。
同梱ファイルdocs/README.mdreferences/unit-test-quality.md
詳細
テストカバレッジの拡充
未テストの分岐やエッジケースを対象にして、ユニットテストのカバレッジを拡充します。
使用するタイミング
- ユーザーが「テストカバレッジを上げる」「テストを追加する」「ユニットテストを拡充する」「エッジケースをカバーする」と依頼した場合
- CI パイプラインでカバレッジが低いと報告され、ユーザーが改善を希望している場合
- コードレビューで、未テストのエラーパスや境界条件が指摘された場合
- リリース前に、既存のテストスイートの不足箇所を特定して埋めたい場合
スタック(ワークフローのステップ 1 の前に検出)
プロジェクトのマニフェストファイルから言語を検出し、以下のワークフロー全体で該当するコマンドを使用します。
| マニフェスト | スタック | カバレッジコマンド | テストフレームワーク |
|---|---|---|---|
package.json | JavaScript/TypeScript | npx jest --coverage or npx vitest --coverage | Jest、Vitest、Mocha |
pyproject.toml | Python | pytest --cov=. --cov-report=term-missing | pytest、unittest |
go.mod | Go | go test -coverprofile=coverage.out ./... | testing、testify |
Cargo.toml | Rust | cargo tarpaulin or cargo llvm-cov | 組み込みのテストフレームワーク |
これらのマニフェストが見つからない場合は、エッジケース — 「テストフレームワークが検出されない場合」を参照してください。
編集前のリポジトリ同期(必須)
既存のリポジトリでファイルの作成・更新・削除を行う前に、現在のブランチをリモートと同期してください。まず、同期前の一覧として git status --porcelain を保存します。ステップ 4 では、これらのパスをステージングしません。
branch="$(git rev-parse --abbrev-ref HEAD)"
git fetch origin
git pull --rebase origin "$branch"
作業ツリーがクリーンでない場合は、先にスタッシュしてから同期し、その後復元します。
git stash push -u -m "pre-sync"
branch="$(git rev-parse --abbrev-ref HEAD)"
git fetch origin && git pull --rebase origin "$branch"
git stash pop
origin が存在しない場合、pull を利用できない場合、または rebase/スタッシュで競合が発生した場合は、作業を中止し、続行する前にユーザーに確認してください。
ワークフロー
0. フィーチャーブランチを作成する
変更を加える前に、以下を行います。
git rev-parse --abbrev-ref HEADを実行します。出力されたブランチがmainまたはmasterではなく、このタスク用に作成されたものなら、ステップ 1 に進みます。git branch -aを実行し、既存のブランチでよく使われている接頭辞(例:feat/、feature/、test/)を確認します。- その接頭辞を使って新しいブランチを作成し、切り替えます。接頭辞が使われていない場合は、ブランチ名を
feat/test-coverageにします。
1. カバレッジを分析する
上記の検出済みスタックに対応するカバレッジコマンドを実行します。合計カバレッジ率と成功/失敗件数をベースラインとして記録します。テストが 1 件でも失敗した場合は、ここで中止します(エッジケースを参照)。
レポートから以下を特定します。
- 未テストの分岐とコードパス
- カバレッジが低いファイル/関数(カバレッジが 60% 未満のファイルを優先)
- 不足しているエラーハンドリングのテスト
2. テストの不足箇所を特定する
カバレッジが低いコードを確認し、以下を調べます。
- 論理分岐(if/else、switch)、状態遷移、副作用
- 実際のバグが潜みやすいエラーパスと無効な入力
- 境界値:空、null、ゼロ、最小値、最大値、オフバイワン
- 既存のテストでカバーされていない正常系のパス
3. テストを書く
references/unit-test-quality.mdを読みます。- 検出済みのスタックに対応するテストフレームワークを使い、ステップ 2 で特定した不足箇所のテストを書きます。そのファイルのルールに従い、決定的で、独立しており、高速で、テストごとに 1 つの振る舞いを検証し、実装ではなく振る舞いをアサーションします。
- 新しいテストをそれぞれ、そのファイルに記載された 4 つのセルフチェック項目で確認します。1 つでも満たさないテストは書き直します。
4. 改善を検証する
- テストスイート全体を実行します。以前は合格していたテストが失敗した場合は、PARTIAL と報告し、そのテスト名を挙げます。新しいテストが失敗した場合は、そのテストだけをさらに2回実行します。単独での実行でいずれか一度でも合格した場合は、不安定なテストです。項目2に従って対処してください。3回すべて失敗した場合に限り、失敗内容を読み、どちらに問題があるか判断します。
- テストに誤りがある(セットアップが不適切、またはコードが決して保証していない動作を期待している):テストを修正し、再実行します。
- コードに誤りがある(テストが、コードの docstring、型、または名前が保証する動作を検証している):バグの疑いがあります。そのテストと、そのテストだけが使用する import または fixture を削除し、項目1を再実行します。本番コードは変更せず、コードに合わせてアサーションを緩めないでください。テストのコードと失敗時の出力を
Decision:に記載して、バグを報告します。実行結果はCOMPLETEでもかまいません。その場合は、Result:の行にバグ名を記載します。そのテストは修正時のリグレッションテストになります。 - どちらに問題があるか判断できない:バグの疑いとして扱います。
- 新しいテストだけを単独で2回実行します(例:
pytest tests/test_parser.py、go test ./internal/store -count=1 -run '^TestKey'、cargo test key_)。いずれかの実行で新しいテストが失敗した場合は、テストの実行順序、共有状態、またはタイミングに依存しています。references/unit-test-quality.mdの不安定なテストに関する表を参考に、一度修正してから項目1と2を再実行します。それでも失敗する場合は削除し、Uncertainty:に記載します。 - Step 1 と同じカバレッジコマンドを実行します。
- 新しい合計値を Step 1 のベースラインと比較します。厳密に上回っていない場合は、PARTIAL と報告し、Step 2 の未テストのままの項目を列挙します。
- 項目1でテストスイート全体が合格し、項目2で新しいテストファイルが合格した場合は、前後のカバレッジ率と新たにカバーされたファイルを記載したメッセージで、フィーチャーブランチに新しいテストをコミットします。この実行で作成した各テストファイルは、明示的なパスを指定してステージします(
git add tests/test_parser.py)。ユーザーの作業を Repo Sync が復元したファイルまで取り込んでしまうgit add -A、git add .、git commit -aは決して使わないでください。事前同期リストにあるパスはステージしないでください。変更されたマニフェストまたはロックファイル(カバレッジツール未インストール)をステージする場合は、コミットメッセージにその理由を記載する場合に限ります。コミットする前にgit diff --cached --name-onlyを確認します。ステージされずに残った変更ファイルをすべてUncertainty:に列挙します。コミットをスキップする場合(テストスイートの失敗またはリグレッション)は、新しいテストファイルをすべて列挙します。 - 最終レポートを出力します。冒頭は
Result:とし、その後にCOMPLETE、PARTIAL — 理由、またはBLOCKED — 理由を記載します。続けて、以下を記載します。Evidence:実行したコマンド、実行前後の合計値、合格・失敗数、および項目2の再実行結果Uncertainty:確認できなかった内容(例:除外されたパス、未実行の CI、出力アサーションのないカバー済み行)Decision:承認が必要な対応、またはNo approval needed。その後、残っているユーザー側の作業(例:ブランチを push する、PR を作成する)- 新しいテストケースの数と、カバレッジの増加が最も大きかったファイル
想定される出力
Python プロジェクトで実行が成功した場合、最終検証レポートは次のようになります。
Result: COMPLETE — coverage 61% → 84%, all tests pass
Evidence: pytest --cov=. --cov-report=term-missing (before): 61% (47/77 statements), 47 passed
same command (after): 84% (65/77 statements), 56 passed, 0 failed
9 new tests run on their own, twice: 9 passed both runs
Uncertainty: CI not run; src/vendor/ excluded from coverage
Decision: No approval needed. Next: push feat/test-coverage and open a PR.
New tests added: 9
Files improved:
- src/parser.py 52% → 91% (+7 tests: null input, empty string, unicode overflow)
- src/auth.py 71% → 88% (+2 tests: expired token, missing header)
受け入れ基準
以下すべてを満たすと、実行は合格です。
- 検出されたスタックで実行可能なコマンドによるカバレッジレポートが存在します(例:
jest --coverage、pytest --cov、go test -cover)。 - 実行後の総カバレッジが実行前のベースラインを厳密に上回っています。指標を改善しないテストの追加は認められません。例外はベースラインが 100% の場合です(「エッジケース」を参照)。
- 新しいテストは、既存のアサーションの重複ではなく、これまでテストされていない分岐、エラーパス、境界値を対象としています。
- 新しいテストはすべて、戻り値、発生したエラー、または観測可能な効果をアサートします。コードを実行するだけのテストはカウントされません。
- 新しいテストでは、ネットワーク、実時間、シード未設定の乱数、
sleep()、または既存のユニットテストで使われているテスト用データベースのフィクスチャ以外の実データベースを使用しません。 - コミット前にローカルでテストスイート全体が合格し(
npm test、pytest、go test ./...など)、新しいテストを単独で 2 回実行しても合格します。 - バグの疑いを明らかにした新しいテストはコミットに含めず、
Decision:に報告します。コードに合わせるためにアサーションを緩めていません。 - 新しいテストはすべてフィーチャーブランチ(例:
feat/test-coverage)上にあり、main/master上にはありません。 - コミットメッセージに、変更前後のカバレッジ率と新たにカバーされたファイルを記録します。
- コミットには今回の実行で書き込んだファイルだけを含め、明示的なパスを指定してステージングします。
項目に不合格がある場合、最終レポートに PARTIAL または BLOCKED とその理由を記載します。
最終レポートは、内容が理解できるものでなければなりません。
- 1 行目に
COMPLETE、PARTIAL、BLOCKEDのいずれかと、その理由を記載します。 Evidence:(実行したコマンドと観測された合計値)とUncertainty:(前提と未確認の動作)を分けて記載します。- 各カバレッジ数値について、コマンド出力を根拠としてたどれるようにします。変更前後の合計値と、ファイルごとの割合を記載します。
Decision:に必要な承認を記載するか、No approval neededと記載し、ユーザーに残っている作業も明記します。
これらは指示の確認項目です。レビュー担当者からのフィードバックがなければ、レポートが人に理解されたかどうかは確認できません。エージェントによる検査では確認できません。
エッジケース
- テストフレームワークが検出されない場合:スキルは
package.json、pyproject.toml、Cargo.toml、またはgo.modを確認してテスト依存関係を探します。見つからない場合は、テストを書く前に、使用するフレームワークをユーザーに尋ねます。 - カバレッジツールがインストールされていない場合:ツールがないためカバレッジコマンドに失敗した場合は、開発依存関係としてインストールし(
pytest-cov、nyc、cargo tarpaulinなど)、コマンドをもう一度実行します。再度失敗した場合は停止し、エラー出力とともにBLOCKEDを報告します。 - 既存のテストがすでに失敗している場合:ステップ 1 のベースライン実行でテストの失敗が報告された場合は、新しいテストを書かないでください。停止し、失敗したテストの名前とともに
BLOCKEDを報告します。 - すでにカバレッジが 100% の場合:ステップ 1 のベースラインが 100% なら、テストを追加しません。ベースラインを根拠として
COMPLETEを報告し、停止します。 - 生成コードまたはベンダーファイルがカバレッジレポートに含まれる場合:自動生成されたパスとサードパーティーのパス(例:
node_modules/、vendor/、dist/、build/、生成コードを示すヘッダーを含むファイル)をステップ 2 のギャップ一覧から除外し、Uncertainty:に記載します。 - 非同期/並行コードパスの場合:フレームワークの非同期テストユーティリティ(例:
pytest-asyncioや Jest のフェイクタイマー)を使用します。同期ラッパーをそのまま使ったり、非同期処理を待つためにsleep()を使ったりしてはいけません。 - コードがクロック、乱数、またはグローバル状態を直接読み取る場合:テスト対象のモジュールがインポートする名前に対する pytest の
monkeypatch、jest.spyOnまたはvi.spyOn、あるいは時間制御用の Jest または Vitest のフェイクタイマーなど、テストフレームワークに付属するツールを使って置き換えます。そのようなツールで置き換えられない場合は、テスト用の接点を設けるために本番コードをリファクタリングしないでください。そのギャップはテストせず、Uncertainty:に記載します。
ステップ完了レポート
各主要ステップの完了後、次の形式でステータスレポートを出力してください。
◆ [Step Name] ([step N of M] — [context])
··································································
[Check 1]: √ pass
[Check 2]: √ pass (note if relevant)
[Check 3]: × fail — [reason]
[Check 4]: √ pass
[Criteria]: √ N/M met
____________________________
Result: PASS | FAIL | PARTIAL
チェック名は、そのステップで実際に検証する内容に合わせてください。合格には √、不合格には × を使い、補足が必要な場合は — に続けて簡潔に記述してください。「Criteria」行には、達成した受け入れ基準の数をまとめます。「Result」行には、全体的な判定を記載します。
ブランチ設定フェーズのチェック: Feature branch created、Base coverage measured
分析フェーズのチェック: Coverage report parsed、Gaps identified、Priority ranked
テスト作成フェーズのチェック: Tests written、Self-check passed、No network, DB, clock, randomness, or sleep、Framework conventions followed
検証フェーズのチェック: Tests pass、New tests pass on their own、Coverage improved、No regressions
ガイドライン
- プロジェクトで既に使われているテストパターンと命名規則に従ってください。
- 新しいテストは、そのユニットを既にテストしているファイルに追加してください。そのようなファイルがない場合は、プロジェクトのユニットテストが置かれている場所、つまりソースコードの隣(Go の
_test.go、Rust の#[cfg(test)]モジュール)またはユニットテスト用ディレクトリに配置してください。統合テストや E2E テストには追加しないでください。