Agent Skills: Test Coverage Guard

既存テストの信頼性を検証し、偽陽性を検出・排除するガードレール。テストがGREENになった後に発動する。「このテスト信頼できる?」「偽陽性」「カバレッジ稼ぎ検出」で発動。

UncategorizedID: TakumiOkayasu/dotfile-work/test-coverage-guard

Install this agent skill to your local

pnpm dlx add-skill https://github.com/TakumiOkayasu/dotfile-work/tree/HEAD/common/skills/test-coverage-guard

Skill Files

Browse the full folder contents for test-coverage-guard.

Download Skill

Loading file tree…

common/skills/test-coverage-guard/SKILL.md

Skill Metadata

Name
test-coverage-guard
Description
既存テストの信頼性を検証し、偽陽性を検出・排除するガードレール。テストがGREENになった後に発動する。「このテスト信頼できる?」「偽陽性」「カバレッジ稼ぎ検出」で発動。

Test Coverage Guard

トリガー条件

キーワード(いずれか)

  • 「テストレビュー」「テストの品質」「偽陽性」「false positive」「テストが信頼できない」
  • 「モックが多すぎる」「カバレッジは高いのにバグが出る」「フレイキーテスト」「flaky test」
  • 「テスト削除していい?」「このテスト意味ある?」「test review」「mutation testing」
  • 「テストスイートが通っているのに不安」「テスト全部通るけど大丈夫?」

状況

  • テストGREEN後、スイートの品質に不安がある場面
  • PRレビューでテストコードの品質を確認したい場合

非対象(委譲先)

  • テスト新規作成 → test-driven-development
  • CI/CD設定 → ci-cd
  • セキュリティテスト詳細設計 → security-review

前提条件

  • レビュー対象のテストファイルが存在すること
  • テストが実行可能な状態(環境構築済み)
  • 対象プロジェクトの言語・フレームワークが判明していること

目的

偽陽性: 本来FAILすべきテストがPASSしている状態。緑でも本番で壊れるなら誤った安心感を与えるだけ。

| スキル | 責務 | タイミング | | -------- | ------ | ----------- | | test-driven-development | テスト設計・作成(TDDサイクル) | テストを書く時 | | 本スキル | テスト検証(偽陽性検出・網羅性指摘) | テストGREEN後 |

本スキルはTDDサイクルを中断・上書きしない。不足発見時は「何が不足か」を報告しTDDスキルに委譲。


実行手順

Step 1: スコープ特定

| 戦略 | 適用場面 | | ------ | --------- | | PR差分ベース | PRレビュー・直近変更 | | モジュール単位 | 「この機能のテストをレビューして」 | | リスクベース | カバレッジ低・バグ多・クリティカル機能を優先 | | 全件 | 小規模プロジェクト・初回導入 |

対象範囲が大きい場合は、変更した契約・障害時の影響・実行可能性を根拠に優先順位をつける。


Step 2: 偽陽性スキャン(P1→P2→P3順)

観点別の独立調査

並行調査で独立した検証が増える場合だけ、対象の契約・失敗モードに沿ってsubagentへ分ける。 テスト数やモジュール数は人数を決める根拠にしない。親が十分に読める場合は親が確認する。 使う場合はテストファイル、担当する失敗モード、実際に失敗すべきコード変更、報告形式を明示し、 親が指摘を重複排除して一次ソースを再確認する。dispatchの作法は ${HOME}/.claude/SUBAGENTS.md を参照。

P1(即時修正)

パターン1: アサーション不足

対象の契約を破る到達可能な変更を実行してもテストがPASSするなら、検出すべき失敗を具体的に示す。return null だけを一律に使わず、戻り値・状態変化・副作用から該当するものを確認する。

パターン2: テストダブル過多

Mockの個数だけで判定しない。変更した契約を壊した場合に実際にFAILするかを確認する。外部APIをStubにする場合は実際の型・エラー契約と照合し、DBを含む状態の保証が必要な場合は統合テストで確認する。

パターン3: 呼び出し文脈の欠落

本番フローで前後処理がデータ状態を変える場合、その前処理を再現しているか確認。バッチ・パイプライン・ミドルウェアで起きやすい。

パターン4: privateメソッドの直接テスト

Reflection等でprivate直接テスト → publicメソッド経由の間接検証に置換。 例外(以下すべてを満たす場合のみ):

  1. 同機能の統合テストが既存でPASS
  2. 純粋な計算ロジック(副作用なし)
  3. 統合テストでは網羅困難な境界値
  4. 抽出不適切の理由をコメント明記

P2(次スプリント)

パターン5: 正常系のみ

以下が不足していないか確認:

  • 入力異常: null/空/0/負数/最大値/存在しないID
  • 状態異常: 未認証・権限不足・論理削除済み・ロック中
  • 外部依存異常: タイムアウト・接続エラー・レート制限
  • 境界値: 境界-1 / 境界 / 境界+1 の3点セット

指摘のみ。テスト追加はTDDスキルに委譲。

P3(バックログ)

パターン6: テストデータと本番データの乖離

DB側デフォルト値・バリデーション・関連テーブル連動を再現しているか確認。重要データは本番と同じAPI/サービス経由で作成する。

パターン7: フレイキーの温床

| 原因 | 対策 | | ------ | ------ | | テスト間状態共有 | テストごとにDB/状態リセット | | 非同期待機不足 | waitFor/eventually使用。sleep(固定値) 禁止 | | 外部サービス依存 | テストダブルまたはテストコンテナ | | システム時刻依存 | FakeClockで時刻注入 | | 並列実行リソース競合 | スキーマ分離またはトランザクション分離 |

⚠️ フレイキーテストは原因を調査し、検出している独自の契約を確認したうえで修正する。削除する場合は同じ契約を守る代替テストを先に用意する。

パターン8: スナップショット形骸化 内容確認なしで --update-snapshot している場合は要注意。長さだけで判定せず、重要な契約が更新に埋もれないよう個別のアサーションと差分レビューを確認する。


Step 3: 契約を壊す変更への感度

対象の契約に応じて、戻り値・条件式・重要な副作用などを誤らせる変更を考える。 思考実験は未実行の仮説として記録し、実際にテストがFAILする証拠として扱わない。 安全に試せる場合は隔離環境で最小限の変異を実行し、元のコードへ戻す。 変異後にテストがPASSする場合は、契約が未検証か等価変異かを区別する。

自動mutationを使う場合も、対象範囲・実行した変異・等価変異を記録する。 全プロジェクトへ同じスコアを一律の合否基準として適用しない。

Step 4: テストダブル検証

チェックポイント

  1. テストダブルを通しても、変更した契約を破るとテストがFAILするか
  2. レスポンス一致: 型・フィールド名・ネスト構造が実際と一致しているか
  3. エラーケース: タイムアウト・エラーレスポンス・不正データのStubが存在するか
  4. 自プロジェクトのDB/クラスをテストダブルで差し替えていないか(実物が原則)

| 種類 | 推奨用途 | | ------ | --------- | | Stub | 外部APIの正常/異常レスポンス | | Mock | 通知送信など副作用の発生確認 | | Fake | InMemoryRepository, FakeClock | | Spy | 実処理維持しつつ呼び出し記録 |

| 対象 | 推奨 | | ------ | ------ | | 外部API(決済・SMS等) | Stub/Mock | | 非決定的な値(時刻・乱数) | Fake | | 自プロジェクトのDB | 状態の整合性が要件なら実物の統合テスト。副作用のない単体テストで無条件に実DBを要求しない | | 自プロジェクトの他クラス | 実物(副作用の呼び出し検証が必要な場合のみ Spy 可) |


Step 5: 網羅性の指摘

  • 正常系に対応する異常系テストが存在するか
  • エラーレスポンスの型・メッセージ・ステータスと副作用の不在を検証しているか
  • セキュリティ関連(未認証拒否・他ユーザーリソースへのアクセス拒否)のテストが存在するか
  • 並行性関連(楽観ロック・在庫同時減算・冪等性)のテストが存在するか

不足テストの一覧をレポートに含める。実装はTDDスキルに委譲。

Property-Based Testing(JS/TS: fast-check、Python: Hypothesis)は既存テストの補完として有効。置き換えではない。


Step 6: レポート出力

## テストレビュー結果

### 🔴 要修正(偽陽性リスク: 高)
- **[テスト名]** — パターンN: [具体的な問題] → [修正方針]

### 🟡 改善推奨
- **[テスト名]** — パターンN: [具体的な問題] → [修正方針]

### 🟢 問題なし
- [テスト名]: [検証済みの観点]

### 📊 サマリー
- 検証テスト数: N / 要修正: N件 / 改善推奨: N件 / 問題なし: N件
- 不足テスト候補: [異常系・境界値テストの一覧 → TDDスキルに委譲]

アンチパターン

| 禁止事項 | 理由 | | --------- | ------ | | 不足テストを本スキル内で実装する | テスト作成はTDDスキルの責務 | | TDDサイクルを中断・上書きする | 本スキルは検証専用 | | sleep(固定値) による非同期待機 | フレイキーの原因 | | フレイキーテストの放置 | CI全体の信頼性を下げる | | カバレッジ数値を目標として追う | 価値の低いテストを量産する | | 既存コードへカバレッジゲートを遡及適用 | 価値の低いテスト量産のインセンティブが生まれる |


テスト削除の判断基準

テストの削除は、何を検出していたかを確認し、同じ契約を別のテストが実際に検証する場合に限る。 保守回数やMock数だけで削除しない。

| 対象 | 判断 | | -------- | ------ | | アサーションなし・トートロジー | 検出力を持たせるか、同じ契約の代替を用意して削除 | | 内部実装のみを写すテスト | 外部契約に沿ったテストへ置き換える | | 不安定なテスト | 原因を直し、代替なしの削除で回帰検出を失わない |


カバレッジの正しい使い方

  • 目標ではなくテスト漏れの発見ツールとして使う
  • ラインカバレッジよりブランチカバレッジを重視する
  • ミューテーションスコアを併用してテストの検出力を直接計測する
  • CIゲートは「新規コード/変更コード」に限定する
  • 未カバー行をテスト追加の候補リストとして活用する

関連スキルとの連携

| スキル | 連携ポイント | | -------- | ------------ | | test-driven-development | 不足発見時はTDDスキルに戻ってテストケースを追加。本スキルは指摘まで | | ci-cd | テストの段階実行、CIゲート設定 | | security-review | セキュリティテストの詳細設計 | | measure | テスト実行時間のボトルネック調査 |