mcpField
C
codebase:testing

codebase:testing

github.com/yeluyangテスト・品質239 回インストール15 週間前に更新
リポジトリ

codebase:testing について

codebase:testing は、本番コードのユニットテストを計画、監査、補完、整理するスキルです。既存テストを見る前のケース設計、関数単位の分離、網羅性を保った重複削減を重視します。

主な機能

  1. 01既存テスト確認前にケースを計画
  2. 02入力と分岐ごとに網羅性を監査
  3. 03依存先をモックして単体を分離
  4. 04プロジェクトの流儀で不足分を追加
  5. 05網羅性を維持して重複を削除
  6. 06整理後にテストスイート全体を実行

活用シーン

  1. 01ファイルやパッケージのテスト網羅性を評価
  2. 02本番コードのテスト漏れを特定
  3. 03冗長または壊れやすいテストを削減
  4. 04監査を反復して網羅性の改善を収束

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/yeluyang/skills --skill codebase:testing

インストール後、Claude Code で/codebase:testingを入力して読み込まれたか確認します。

同梱ファイルagents/openai.yaml

詳細

単体テスト

対象範囲の本番コードに対する完全な単体テストケースシステムを計画し、既存のテストでカバーされている内容を確認して、不足を補い、最後に整理します。基本的な方法論は、まず理想的なケースシステムを考え、それを現状と比較することです。これにより、既存のテストに引きずられたり、見落としが生じたりするのを防ぎます。

基本原則

  • 監査の前に計画する:各関数/メソッドにどのようなテストケースが必要かを独自に計画してから、既存のテストで何が実現されているかを確認します。先に既存のテストを見るとバイアスがかかり、「十分そうだ」という感覚から、本来テストすべき内容を見落とすことになります。
  • テスト対象の単体を分離する:関数 A をテストする際に A が B を呼び出す場合、B は正しいものとして扱い、B をモックして、B とのやり取り(入出力)が期待どおりかどうかだけを検証します。B が正しいことを証明するために、A のテスト内でさまざまなケースを決して詳しく検証しないでください。B には独自のテストがあります。この境界を崩すと、協力先のバグによって、それを呼び出すすべての関数のテストが一斉に失敗し、原因の特定が混乱します。
  • 書けないテストは受け入れる:単体テストの中には、モックのコストが高すぎる、テストデータを用意できない、巨大なクラスのため徹底したテストが難しいなど、本当に書きにくいものがあります。これは実行者の責任ではありません。脆弱なテストや実質的に意味のないテストを無理に作るのではなく、きっぱりと対象から外してください。対象から外す場合は、ケース計画にその理由を記録します。
  • 繰り返し実行するたびに収束する:このスキルは、不足を見つけて補うために繰り返し実行される場合があります。健全な繰り返し実行の結果は「追加がごく少数」であり、実行のたびに新たな不足が大量に見つかる状態ではありません。毎回多くの不足が見つかるなら、問題はコードではなく、計画や監査の深さにあります。

スコープ

ユーザーの引数を解析し、単体テストを作成するスコープを判断します。

ユーザー入力スコープ
引数なしプロジェクト全体 — すべての本番コードを対象に関数ごとに計画します
ディレクトリまたはパッケージのパスそのサブツリー — その中にあるテスト可能な本番コードをすべて分析します
特定のファイル、クラス、またはメソッドその対象のみ — その対象のケースを計画します

スコープが明確になったら、ステップ 1〜4 を順番に実行します。

ステップ 1:ケースシステムを計画する

スコープ内の各関数/メソッドについて、それに必要なテストケースシステムを計画します。計画中は既存のテストを見ないでください。

ケース計画は、次の 3 つの観点から進めます。

1.1 明示的なパラメーターの値の組み合わせ

パラメーターのあらゆる組み合わせを網羅的に列挙するのではなく、関数のロジックに応じた代表的な値の組み合わせを設計します。

  • スモークケース:ゼロ値、空の値、極端な値などの課題を持ち込まず、関数の期待に沿った一連の引数を使います。最も基本的な入力で関数が正しく動作することを確認し、回帰テストの基準とします。
  • ゼロ値:各型のゼロ値(0、""、false、nil/null/None)。
  • 空の値:空文字列、空配列、空のコレクション、空のマップなど、さまざまな空のコンテナー。
  • パラメーター型の上限/下限:スカラー型では、int/uint/float32 の最大値/最小値などの境界値と、浮動小数点数の正負のゼロおよび精度の境界を指定します。
  • コンテナーの要素数:「空の値」ですでに空のコンテナーをカバーしているため、さらに単一要素のコンテナー(要素数がちょうど 1)と複数要素のコンテナー(要素数が 2 以上)を追加し、反復処理、先頭/末尾の要素、オフバイワンの挙動をカバーします。
  • 不正な入力:列挙型のパラメーターに列挙型のメンバーではない値を渡すケースや、パラメーターに対する関数の検証仕様に違反する入力が含まれます。
1.2 暗黙の入力の値の組み合わせ

関数の入力は、パラメーターに限られません。次の「暗黙の入力」についても、値の組み合わせを設計する必要があります。

  • グローバル変数:関数が参照するパッケージレベルまたはグローバル変数です。異なる値や状態を考慮します。
  • クラスのメンバー変数:クラスのメソッドがアクセスするインスタンスフィールドです。状態の異なるオブジェクトを構築します。
  • 外部呼び出し:関数が呼び出す他の関数、メソッド、ネットワーク/ファイル/データベース操作です。これらの暗黙の入力は主にモックを通じて扱います。ただし、ここでカバーするのは、モック対象の関数の入力値の組み合わせではなく、その戻り値の組み合わせである点に注意してください。正常な戻り値、境界となる戻り値、そしてエラーをスローするケースを対象にし、テスト対象の関数が協力先のさまざまな出力を処理できることを検証します。
1.3 ロジックの分岐

関数本体内の制御フローの分岐を洗い出します。

  • if/switch の分岐:各分岐を実行する値の組み合わせ(明示的なパラメーターまたはモックの戻り値)を設計します。
  • エラー処理ロジック:協力先のエラーを捕捉した後に、テスト対象の関数がとる再試行、変換、伝播、縮退の各経路です。エラーを返す値をモックして、これらの経路を実行します。
  • テストする価値のない分岐:メッセージをログに記録するだけ、またはエラーを変更せずそのまま渡すだけなど、それ自体に検証可能な動作がない分岐もあります。アサーションが必要な出力や状態変化がないため、テストケースを設計する価値はなく、スキップできます。
  • 到達が困難な分岐:単体テスト環境ではトリガー条件を構築するのが非常に難しい分岐は、「書けないテストは受け入れる」という原則に従って除外し、その旨を記録します。

ステップ 2:既存のテストを監査する

次に既存のテストを確認し、以下の2点を行います。

2.1 テストのスタイルを把握する

追加するケースが既存のテストになじむよう、コードベースの単体テストの規約を把握します。

  • テストの命名規則
  • テストファイルのディレクトリと命名規則
  • 使用しているテストフレームワークと構成(テーブル駆動、サブテスト、describe ブロックなど)
  • モックツールとモックの使用方法
  • アサーションのスタイル、セットアップ/ティアダウンの規約
2.2 カバレッジと照らし合わせる

ステップ 1 の計画を既存のテストとケースごとに比較し、計画のどの部分がすでにカバーされているかを判断します。判断にあたっては、次の点に注意してください。

  • 既存のテストが同じ関数の同じ側面をカバーしている場合は、カバー済みとし、重複するケースは追加しません。
  • 既存のテストが、計画で想定していなかったシナリオをカバーしていることもあります。それが本当に残す価値のあるケースかどうかを評価し、価値があれば計画に取り込み、そうでなければ削除候補として記録します。
  • 監査はケースの側面まで掘り下げ、値の組み合わせ(明示的・暗黙的を問わず)を詳しく確認する必要があります。「この関数にはテストがある」というところで止めてはいけません。関数にテストがあることと、徹底的にテストされていることは同じではありません。

収束のセルフチェック(重要):既存のテストがかなり網羅的に見えるのに、なお大量の新しいケースを提案している場合は、いったん止まって再検討してください。このスキルは、抜けを検出して埋めるために繰り返し実行されることがよくあります。期待される結果は収束です。実行するたびに大量の抜けを挙げるべきではありません。以下のどの状況に当てはまるのか、率直に判断してください。

  • これまでの実行で、実際にケースを追加しそびれていた:今回一度で補完し、以降の実行で収束させるにはどうすればよいでしょうか。形式的に少数のケースを追加するのではなく、カバーすべき側面を網羅して徹底的に補完してください。
  • 既存のシステムですでに十分である:作業量を増やすために、役立ちそうに見えても実際には重複または無意味なケースを大量に挙げていませんか。削除してください。
  • 既存のシステムへの理解が不十分である:既存のテストがすでにカバーしている側面を見落とし、それを抜けと誤って判断していませんか。2.2 に戻り、さらに細かく監査してください。

ステップ 3:不足しているケースを追加する

既存のテストスタイルに沿って、計画に含まれていて、既存のテストではまだカバーされていないケースを追加します。

作成が難しいテスト(モックのコストが高い、データを準備できない、ゴッドクラスなど)については、「書けないテストは受け入れる」という原則に従って除外し、脆弱なテストを無理に作成しないでください。

ステップ 4:テストケースを整理する

対象範囲のテストから、カバレッジを維持したままコードを減らします。

  • 重複するケースを削除する:同じ関数の同じ観点をカバーするケースが複数ある場合、最も正確なものを残します。
  • 価値のないケースを削除する:テストとしての意味がないケースを削除します。たとえば、ゲッターやセッターだけをテストするケース、常に成功するアサーション、すでに存在しないコードをテストするケース、誤った動作を検証するケースなどです。
  • より良いイディオムで簡潔にする:プロジェクトでサポートされているイディオム(テーブル駆動、パラメーター化、共通セットアップ/ヘルパー)を使って、同じ数のケースをより簡潔なコードでカバーします。簡潔にする際は、失敗した場合に特定のシナリオを特定できるラベルを各ケースに付けてください。
  • カバレッジを損なわない:整理後も、テスト対象の関数について、各観点のケース数を整理前より減らしてはいけません。削減するのは重複や冗長なコードだけであり、カバレッジではありません。

整理後、テストスイート全体を実行し、成功していること(または意図的にスキップしたケースだけが残っていること)を確認します。

コメント