mcpField
T
testing-best-practices

testing-best-practices

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

testing-best-practices について

testing-best-practicesは、ソフトウェアテストの作成とレビューを支援するスキルです。Write、Assess、Upgrade、Detectの4モードで、言語やフレームワーク、テスト種別に応じた指針を提供します。

主な機能

  1. 01テスト作成とテスト先行の修正
  2. 02テストスイートの品質評価
  3. 03弱いテストや不安定なテストの強化
  4. 04スキップされたテストや誤解を招くテストの検出
  5. 05言語とトピックに応じた資料選択

活用シーン

  1. 01バグ修正のテスト追加
  2. 02カバレッジ以外の観点でテストをレビュー
  3. 03不安定なテストや過剰なモックの改善
  4. 04スキップされたテストやカバレッジの欠落を発見

インストール

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

$npx skills add https://github.com/adewale/testing-best-practices --skill testing-best-practices

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
antipatterns.md
characterization-testing.md
combinatorial-testing.md
correctness-by-construction.md
deterministic-time.md
differential-testing.md
doc-sync-testing.md
exhaustive-testing.md
fuzzing.md
gate-integrity.md
go.md
golden-file-testing.md
mathematical-properties.md
mutation-testing.md
property-based-testing.md
python.md
rust.md
test-data-builders.md
test-types.md
typescript.md
vcr-cassettes.md

詳細

テストのベストプラクティス

このスキルには、次の4つのモードがあります。

  1. 作成 — テストを追加する、またはテストファーストでバグ修正や機能追加を行います。
  2. 評価 — 網羅率だけでなく、既存のテストスイートの品質をレビューします。
  3. 改善 — 品質の低いテスト、不安定なテスト、過剰にモックを使ったテストを強化します。
  4. 検出 — スキップされたテスト、改ざんされたテスト、見かけ上の網羅率を装うテスト、または抜けが生じやすいテストを見つけます。

最初の90秒

テストの作成、評価、変更を始める前に、次のことを行います。

  1. リポジトリ内のファイルと近くにあるテストから、言語とフレームワークを特定します。
  2. 命名規則、フィクスチャ、ビルダー、アサーションのスタイル、ランナーの実行コマンドを確認するため、近くにあるテストを読みます。
  3. 広範な全テストスイートのコマンドを実行する前に、最も関連性の高い検証コマンドを見つけます。
  4. リスク境界を特定します。純粋なロジック、内部コンポーネントの境界、外部 API、UI/ユーザージャーニー、セキュリティ境界、悪意のある入力を扱うパーサー、型/スキーマの不変条件のいずれかです。
  5. 変更と対象を分類します。動作の変更か、構造の整理か。再利用可能なライブラリか、一時的な検証用コードか。顧客向けのルールか、内部ヘルパーかを判断します。
  6. references/test-types.md から、必要最小限のテスト層を選びます。
  7. 以下の一覧から、関連するリファレンスのみを読み込みます。

言語専用のリファレンスがない場合は、プロジェクトの規約と、ここに記載されている一般原則に従ってください。

リファレンス一覧

必ず確認してください:

  • テスト種別の選択 → references/test-types.md
  • アンチパターンの検出 → references/antipatterns.md

言語/フレームワークのリファレンス:

  • Python / pytest / Hypothesis → references/python.md
  • TypeScript/JavaScript / Vitest/Jest/fast-check/Playwright → references/typescript.md
  • Go / testing / testing.F / Rapid → references/go.md
  • Rust → references/rust.md

プロパティベーステストまたはカバレッジ誘導型ファジングを行う場合は、対応する言語のリファレンスも読み込んでください。収集、検出、リプレイの動作はエンジンによって異なります。選択したエンジンがここに記載されていない場合は、別のエンジンの動作を当てはめず、そのプロジェクトのドキュメントに従ってください。

トピック別のリファレンス(該当する場合):

  • プロパティテストの作成/レビュー、プロパティの選択、ジェネレーターの設計、状態ベース/モデルベーステスト、シードとリプレイ → references/property-based-testing.md
  • 外部公開された/カスタムのパーサー、ネイティブまたは unsafe なデコーダー、クラッシュしやすい境界、クラッシュによってチェックが無効になるセキュリティツールを対象とする、カバレッジ誘導型のターゲットまたはキャンペーン → references/fuzzing.md
  • レガシーコード/リファクタリングの安全性 → references/characterization-testing.md
  • 再実装、移植、複数言語の SDK、参照実装のないカスタムデータ構造、または近似/確率的/ANN/ランキング出力 → references/differential-testing.md
  • 複雑な出力、スナップショット、変換パイプライン、保存/読み込みまたは移行のラウンドトリップ → references/golden-file-testing.md
  • 時刻、タイマー、スケジュール、スリープ、不安定な時刻テスト、スリープしないと到達できないバックグラウンドスレッド/非同期処理のテスト → references/deterministic-time.md
  • 外部 API、記録された実際の応答、モックのずれ → references/vcr-cassettes.md
  • CLI/プラグイン/ドキュメントのレジストリ同期、またはドキュメントやエージェントの指示における検証の主張 → references/doc-sync-testing.md
  • ミューテーションテスト、ミューテーションスコア/生存ミュータント、定期的に実行するミューテーションのレーン、または高いカバレッジにもかかわらずバグがすり抜ける場合 → references/mutation-testing.md。定期実行については、完了したターゲット CI のベースラインも、障害クラスを検出できることの実証もない場合、スケジュールを設定しないでください。絶対的なスコア下限をそのまま適用しないでください。
  • 有限状態空間またはコストの高い直積 → references/exhaustive-testing.md
  • 大規模な設定/機能/ランタイムのマトリックス、ペアワイズテストへの置き換え、または相互に影響する要因 → references/combinatorial-testing.md。固定された回帰テストと正確なレジストリ登録を維持し、名前付きの可変強度グループと、削除前のシャドーエビデンスを使用してください。
  • 算術演算子/ドメイン演算子/法則 → references/mathematical-properties.md
  • フィクスチャー/ビルダー/アサーションヘルパー → references/test-data-builders.md
  • 複数レイヤーで同じ不変条件を確認する場合、型とテストの選択、無効な状態 → references/correctness-by-construction.md
  • CI/フック/テスト設定の変更、ゲート付きまたはスケジュール実行されるテスト層、「このチェックは実行され、失敗する可能性があるか?」の確認、デプロイ検証 → references/gate-integrity.md

基本原則

公開コントラクトを通じて動作をテストする

優れたテストは、出力、状態遷移、副作用、描画された UI、永続化されたデータ、API コントラクト、不変条件など、観察可能な動作を記述します。動作を維持するリファクタリングで壊れるようなテストは避けてください。たとえば、プライベートメソッド、偶発的な呼び出し順序、SQL 文字列の完全一致、または広範なモックの呼び出し順序などです。

ユーザーから例、表、バグ報告、スプレッドシートの行、サポート事例が提示された場合は、まずそれらをコミュニケーション上の資料として扱い、アサーションとして扱うのはその次です。ビジネスで使われる表現を維持したうえで、最も狭く、かつ実態に即した接点(通常はドメイン/サービス/API コントラクト)で例を実行してください。ビジネスルールの行ごとに UI 全体の経路を通す必要はありません。UI/E2E テストでは配線とゴールデンパスを検証し、ルールの表はドメイン層を直接テストしてください。

成果物の寿命と変更の種類に応じてテストへの投資を調整する

すべての成果物に同じテスト計画を適用しないでください。再利用可能なライブラリ、パーサー、決済/認証/セキュリティの境界、マイグレーション、リファクタリングを予定しているコードには、より充実した回帰テスト/プロパティテスト/コントラクトテストが必要です。一時的なプローブ、単発の調査用スクリプト、生成された探索用コードは、そのライフサイクルをユーザーが受け入れる場合、スモークチェックだけで済ませるか、テストを行わなくてもよいことがあります。

動作の変更と構造の変更を分けて考えてください。動作の変更では、新しい動作や変更された動作に対して失敗するテストが必要です。単なる整理やリファクタリングは、既存の成功しているテストスイートを活用してください。そのようなテストスイートがない場合は、リファクタリングの前に、維持する必要がある動作を特性化するテストを追加してください。

パイプラインのない新しいサービスでは、最小限のビルド/デプロイ/テストの一連の流れであるウォーキングスケルトンから始めてください。未完了の受け入れテストは、黙ってスキップするのではなく、ストーリーや課題に関連付けた進行中の項目として見えるようにしてください。ユニットテストは成功状態を保ち、証明として失敗するユニットテストをコミットしないでください。

実現可能な場合はレッド・グリーン・リファクターを行う

バグ修正や新しい動作の追加では、次の手順を基本としてください。

  1. レッド — 現在のバグや未実装の動作に対して失敗する、焦点を絞ったテストを追加します。
  2. グリーン — テストに合格する最小限の変更を実装します。
  3. リファクター — テストが成功した状態を保ちながら整理します。

証拠が重要です。レッドの証拠(修正前の正確なコマンドと失敗した出力)と、グリーンの証拠(修正後の成功したコマンド/結果)を分けてください。両方がこの順序で確認できた場合に限り、TDD/レッド・グリーン・リファクターを完了したと主張してください。成功した実行結果しかない場合は、テストを追加して現在は合格しているものの、レッドの段階は確認されていない/未検証であると述べてください。成功結果だけのログから、後付けでTDDを実施したと主張しないでください。探索的なプロトタイプ、生成されたコード、またはユーザーが「テストのみ」と指定したタスクでは、スコープ内にとどまり、逸脱があればその旨を明記してください。

TDDを実践するときは、見える形でテストリストを維持してください。新たに見つかったエッジケースのアイデアは、作業サイクルの途中で追いかけず、リストに記録します。行き詰まった場合は、進め方を簡単にしてください。まずアサーションを書く、より小さな子テストを切り出す、サードパーティ API の学習用テストを書く、またはクラッシュテストダミーのフェイクを使って扱いにくいエラーパスを発生させる、といった方法があります。不確実性に応じて Fake It、Triangulate、または Obvious Implementation を選び、フェイクの定数を最終的な動作として残さないでください。

網羅性より品質を重視する

網羅性からわかるのは、何が実行されたかであり、バグを検出できることが証明されるわけではありません。行カバレッジより分岐カバレッジを優先し、カバレッジは未テストの経路を見つけるための地図として使います。カバレッジだけを品質の合格基準にしないでください。

アサーションの数は目安であって、絶対的なルールではありません。決してノルマにしないでください。例ベースの動作テストでは、構造、状態、否定的なケースを検証するために、意味のあるアサーションを複数必要とすることがよくあります。一方、プロパティテスト、テーブルの各行、例外テストでは、優れた判定基準が1つあれば十分な場合もあります。「空でない」、toBeDefined()、toBeTruthy()、Assert.IsNotNull(result) のような弱い単独アサーションや、アサーションのないログ出力には注意してください。

サニタイザー、バリデーター、フィルター、認証・セキュリティチェック、変換処理では、該当する場合、両方向を検証してください。危険または無効なコンテンツが拒否または削除されることと、安全または有効なコンテンツが保持されることを確認します。

テスト対象の動作に関係するフィールドをアサートしてください。オブジェクト全体や構造全体の比較では、関係のないすべてのフィールドまで暗黙にアサートされるため、無関係な変更でテストが壊れ、フィールドが追加されるたびにリテラルを更新する作業に追われます。全体の状態比較は、幅広い検証が契約の一部である場合に限ってください。たとえば、ゴールデンファイルや保存/読み込みのラウンドトリップ(references/golden-file-testing.md)が該当します。失敗メッセージだけでデバッグを始められる形式のアサーション(期待値と実際の値を表示するマッチャーや fluent assert など)を優先し、単なるブール値は避けてください。反復順序のような無関係な理由で多くのテストが繰り返し壊れる場合は、テストごとに直すのではなく、アサーションの表現(順序を問わないマッチャーや構造マッチャー)を見直してください。カバレッジでは、リポジトリ全体で単一の数値を設定するのではなく、新規または変更されたコードを対象に基準を設け、レビューでは「カバーされていない部分」に注目してください。

カスタムの判定基準、リンター、バリデーター、修正ツール、評価グレーダーにはすべて、合格する既知の正常な入力と、失敗する既知の不正な入力が必要です。入力は小さく保ち、不正な入力ごとに高コストなチェッカーを再実行しないでください。コードと同じ変更で同じ作成者が用意したゴールデン、承認済みデータ、評価ケースは、独立した判定基準ではなく、現状を記録したものです。

モックより実際の動作を優先する

次の順で優先してください。

  1. 実際のインメモリ/ローカルオブジェクト、一時ディレクトリ、インメモリデータベース、実際のパーサー。
  2. 実際のランタイムをローカルでエミュレートするもの(workerd/vitest-pool-workers、Node 上の Pyodide、wrangler dev、マイグレーションから読み込んだ SQLite)。
  3. 同じインターフェースを実装し、履歴を記録できる、用途に合わせて作成したフェイク。
  4. 制御されたエッジケース向けの決定論的なスタブ。
  5. 最後の手段としてフレームワークのモック。

ダブルの期待値は、モック作成者の思い込みではなく、実際のサービスから取得したもの(記録したもの、またはローカルでエミュレートしたもの)にしてください。実際のエンジンをプロセス内で実行できる場合は、モックを削除してください。

呼び出しの手順より、目に見える状態を優先してください。保存された行、発行されたイベント、レスポンスボディ、ディスク上のファイル、または小さなロギング用フェイクが記録した結果をアサートします。値はモックせず、組み立ててください。自分が所有する役割をモックし、サードパーティライブラリを直接モックしないでください。プロバイダー SDK は自分たちが所有するインターフェースの背後に置き、実際のプロバイダーの形式を確認するためのコントラクトチェックまたは VCR チェックを追加します。インタラクションテストでは、クエリは許容し、コマンドには期待値を設定してください。ゲッターは自由に呼び出せますが、副作用のあるコマンドにこそ期待値を設定する意味があります。

入力空間が広い場合はプロパティベーステストを使う

入力や操作の範囲が広く、サンプルだけでは効率よく網羅できない場合は、プロパティベーステストを使います。意味のある振る舞いを表すプロパティ(往復、冪等性、保存則、メタモルフィック関係、代数法則、小さなモデルとの一致など)を選びます。単に実行時にクラッシュしなかったことを示すだけのものは避けてください。

テスト対象の振る舞いに合わせてジェネレーターを選びます。完全性や文書化されたエラーの確認には任意の入力を、意味上の分岐の確認には仕様に準拠した入力を、ライフサイクルの振る舞いには状態を持つトレースを、カバレッジガイド付きの探索にはコーパスの変異を使います。実装から独立したオラクルを使用してください。プロパティテストツールは値を構築し、失敗を縮小します。カバレッジガイド付きファザーは、新たな制御フローを目指してコーパスを変異させます。これらの用語やツールを同じ意味で使わないでください。

小規模な有限空間では、各セルのコストと、より低コストのレイヤーでプロパティを判定できるか(references/exhaustive-testing.md)を確認したうえで、サンプリングよりも網羅的な生成を優先してください。ジェネレーター、オラクル、実行、再現方法については、references/property-based-testing.mdを参照してください。

無効な入力だけでなく、エラー処理経路もテストする

本番環境における重大な障害の多くは、浅いところで発生します。依存先がすでに失敗したときにしか実行されないエラー処理コード、つまりディスク書き込みエラー、接続切断、タイムアウト、不完全な応答などに潜んでいます。分散システムの壊滅的な障害に関する実証研究では、その大半が、こうした経路を実行する単純なテストで再現可能だったことが示されています。つまり、「異常系」とは、不正な引数を拒否することだけではありません。下流での障害(例外を発生させるフェイク/スタブ、注入した I/O エラー、例外を発生させるside_effect)を注入し、システムが適切に縮退することを検証してください。

望ましい動作ではなく、コードが実際に持つ障害時の動作を検証してください。仕様を読むかコードを確認し、障害時にどう振る舞うべきか(伝播、再試行、ラップ、フォールバック、ロールバック)を把握してからテストします。契約で約束されていない再試行回数の上限、独自のエラー型、ロールバックの意味論を作り出さないでください。それらをテストすると、架空の契約を検証することになり、スコープの逸脱につながります。意図された障害時の動作が仕様にない場合は、現状のコードの動作を特性として記録し、その不足点を、本番環境の新たな動作をテスト内で設計するのではなく、フォローアップ事項として明記してください。

内部不変条件は型/スキーマ/契約に移す

型とテストでは、異なる問いに答えます。

  • 型/スキーマ/契約:「この不正な状態が存在し得るか?」
  • テスト:「観測可能な振る舞いが仕様と一致しているか?」

内部レイヤー間で不変条件が繰り返されている場合は、それを境界パーサー、スマートコンストラクター、スキーマ、シールドされた列挙型、状態機械、またはデータベース制約に移すことを検討してください。チェックやそのテストを削除する前に、以下のすべてを確認してください。

  • コンテキストが内部的で、敵対的ではないこと。
  • 不変条件が型/スキーマ/コンストラクターによって実際に強制されていること。
  • 境界テストが、悪意のある入力や不正な入力を網羅していること。
  • セキュリティ/認証/外部障害の各レイヤーが、異なる障害モードに対処していること。
  • 本番コードの型の変更がスコープ内であるか、明示的に承認されていること。

ユーザーのスコープに「テストのみ」や「本番コードを変更しないでください」とある場合は、現在の API に対するテストを追加し、型/スキーマの厳格化はフォローアップ事項として列挙してください。

レース検出器で並行コードをテストし、並行性の契約を明確にする

複数のゴルーチン/スレッドで使うことを想定したコードでは、逐次テストで証明できることはほとんどありません。多くのワーカーを同時に解放して共有状態を操作し(開始バリアを使うと競合を最大化できます)、レース検出器またはスレッドサニタイザー(go test -race、ThreadSanitizer / -fsanitize=thread、-count による繰り返し実行)の下で実行してください。並行テストが成功しても、逐次テストより得られる証拠は弱いものとして扱ってください。レースは確率的に発生するためです。

たまたま観測したカウントをログに記録して済ませるのではなく、API が実際に保証する不変条件(更新の消失がないこと、単調増加する/線形化可能なカウント、計算が最大 1 回であることなど)をアサートしてください。実装がその契約に違反する可能性があるなら(たとえばロックの外で計算するため、2 つの呼び出しが二重に計算するなど)、それは失敗するテストまたは明示的なフラグで明らかにすべき欠陥です。レースを期待される動作にひそかに組み込む t.Logf で済ませてはいけません。

モード別ワークフロー

作成モード
  1. 近接するテスト/設定を読み、関連する言語リファレンスを読み込みます。
  2. references/test-types.md からテスト階層を選びます。
  3. バグや新しい動作に対しては、可能であれば最初に失敗する回帰テストを追加します。
  4. ユーザー/顧客の例を、すべての例を UI に通すことなく、読みやすいテストケースに変換します。
  5. セットアップのノイズで意図が見えにくくなる場合は、ビルダー/ファクトリー/ヘルパーを使います。カスタムヘルパーがミニ DSL になったら、そのヘルパーもテストします。
  6. 内部実装より、ユーザー向け/公開インターフェースを優先します。
  7. 時間、乱数、ネットワーク、ファイルシステム、順序による非決定性を固定します。
  8. テスト値は意図的に選びます。異なる非デフォルト値を含め、少なくとも 1 つのケースで引数の欠落、デフォルト化、入れ替わりが明らかになるようにします。それでも、境界値または契約の一部である場合は、ゼロ、空、同値のケースもテストします。期待結果は SUT とは独立して導出します。単純な例ではリテラルが最も明確です。より広いケースでは、プロパティや真に独立した参照モデルが適しています。SUT 自身のロジックや定数で期待値を再計算しないでください。テストが同じバグを共有して成功し続ける可能性があるためです。
  9. まず最も関連性の高いテストを実行し、実行可能であれば、さらに広範なチェックも行います。

変換処理や複雑な生成出力には、明示的なレビュー規律とともにゴールデンファイルを使います。references/golden-file-testing.md を参照してください。外部 API には、CI で実際に呼び出すより、記録済みの実データフィクスチャ/カセットまたはコントラクトチェックを優先します。references/vcr-cassettes.md を参照してください。

評価モード

重要度別に根拠を報告し、良い点も含めてください。生成テストについては、エンジン固有の変更を推奨する前に、関連する言語とトピックのリファレンスを読み込んでください。以下を確認します。

  1. 実行されていますか。また、失敗できますか。 各ティアについて、実行するジョブ、デフォルトブランチでの直近の結果、ゲート付きテストが実行可能かどうか、各ゲートが失敗状態になり得るか(|| true、continue-on-error、ベースライン更新ツール、スキップグリーン、空のターゲット)を確認します。機能していないゲートは、最初に指摘すべき事項です。references/gate-integrity.md を参照してください。
  2. サボタージュ/誤った安心感:スキップされたテストや対象を絞り込んだテスト、アサーションがない、アサーションせずにログを出力するだけ、コメントアウトされたアサーション、常に真となるアサーション。
  3. オラクルの強さ:唯一のアサーションが弱い、否定系/エラー/状態/構造に関するアサーションがない、恒真式。プロパティテストでは、意味上の不変条件を利用できる場合、単にクラッシュしないことだけを確認するオラクルは弱いものです。
  4. モックと実環境の乖離:実際の API/スキーマの変更を検知できないハードコードされたモック。
  5. ティアの整合性:ライブネットワークに接続するユニットテスト、実行すると主張するすべての境界をモックする統合テスト、テスト対象のシステムをモックしたり、テスト用ファサード経由で操作したりする E2E テスト、本番環境を対象とする PR スイート、テスト対象の成果物とデプロイされる成果物が同一かどうか。
  6. 決定性:スリープ、実時間の使用、シードなしの乱数、実行順序への依存、グローバル状態の漏出。
  7. カバレッジの品質:分岐網羅率。高カバレッジのスイートでバグが見逃される場合は、重要な経路に障害を仕込み、どのテストが失敗するかを確認します。最も低コストなものから試してください(references/gate-integrity.md §5)。定期的なミューテーションテストレーンを、デフォルトの推奨事項にはしません。
  8. 不変条件を置く場所:型/スキーマ/コントラクトにすべき検証を内部で繰り返している。
  9. ライフサイクルとの適合性:使い捨てのプローブを過剰にテストしている、再利用可能なアセットのテストが不足している、または構造だけの変更に対して振る舞いテストをしているかのように装っている。
  10. 例の品質:ビジネス例が UI スクリプトの奥に埋もれている、フィクスチャが読みにくい、または DSL を形成するヘルパー自体にテストがない。
  11. 生成による根拠:設定されたランナーが本番経路に到達するか、ジェネレーターが主張されたドメインをカバーするか、オラクルが独立しているか、シード再生がアクティブな探索と誤って表示されていないか。複数のランナー、プロジェクト、フィルター、重複したターゲットリストがあり、実行可能性が不明確な場合は、正確な CI 設定を検証します。恒常的に発生するリスクに限り、永続的なドリフト防止策を追加します。
  12. テストコードの可読性(DAMP):テスト本体内のロジック(ループ/分岐/算出される期待値)、SUT 自身の定数から導出された期待値、依存するアサーションから遠く離れた場所で変更される共有フィクスチャ。references/antipatterns.md を参照してください。
  13. スイートの構成:ティアごとのテスト数を数えます。逆ピラミッド/アイスクリームコーン(薄いユニットテストの基盤に対して E2E テストが大半を占める構成)や砂時計型(ユニットテストと E2E テストはあるものの、統合テストが空の構成)を指摘します。ビジネスルールは UI より下の層に移し、各 E2E ケースに適した最小のティアを推奨する一方で、ゴールデンパス/重要なユーザージャーニーをカバーする E2E テストは少数に絞って残します。
アップグレードモード

リスクの高いものから優先してください。

  1. P0:アサーションが弱い、または不足しているセキュリティ/認証/インジェクション/サニタイザーのテスト。
  2. P1:null ではないこと/空ではないこと/truthy であることしかアサートしないテスト。
  3. P2:不安定なテスト:sleep、実際のネットワーク、実時間、順序への依存。待機処理を修正する前に、より小さな SUT でテストを実行できないか確認してください。ツールの選択よりもサイズ(依存関係、プロセス、RAM フットプリント)のほうが不安定さを予測できます。また、自動再試行や隔離は修正ではなく、負債を隠すものとして扱ってください。
  4. P3:モックに大きく依存した「統合」テストや、実装に結びついたモック。
  5. P4:フィクスチャのノイズ、重複、わかりにくい名前、ビルダーの不足。

よくあるアップグレード:

  • sleep() を仮想時間、注入したクロック、または条件ベースの待機に置き換えます。
  • 実際の API 呼び出しを記録済みのカセットまたはコミット済みのフィクスチャに置き換えます。
  • 広範なモックをフェイク、コントラクトテスト、またはパブリックな動作に対するアサーションに置き換えます。
  • 繰り返し使われるオブジェクトリテラルを、動作固有のフィールドを明示するビルダーに置き換えます。

ティアを黙って下げてはいけません。削除または置き換えたテストをティア別に列挙し、同等以上のティアで置き換えない限り、実エンジンを使うテスト(SQLite、workerd、ブラウザー)は維持してください。教訓や事後分析は、チェックによって強制される場合に限り有効です。

検出モード

references/antipatterns.md の具体的な検索シグナルを使います。

  • 実際の条件がない @skip、skip、skipif、test.only、fit、xit、xdescribe。
  • アサーションの代わりに使われている print、console.log、t.Log、Debug.WriteLine。
  • アサーションのないテスト、または truthy/空ではないこと/null ではないことしかチェックしないテスト。
  • 独立したオラクルのないプロパティテスト、簡単な経路に絞り込まれたジェネレーター、列挙できるのにサンプリングされている小さな有限領域。
  • 同期のために使われている sleep、waitForTimeout、Thread.Sleep、Task.Delay。
  • 例外を握りつぶす try/catch。
  • アサーションと同一の戻り値を返すモック。
  • クリーンアップのないグローバル状態/環境変数/レジストリの変更。
  • 差分をレビューしないスナップショット/ゴールデンファイルの更新。
  • || true、continue-on-error、scan --baseline、::warning:: によるスキップを含む CI ステップ。実行されることのないカバレッジまたはミューテーションのしきい値。
  • プログラムとして実行されるミューテーションテスト:変更されていないコードに対するカレンダースケジュール、切りのよい数値の下限、生き残ったミュータントを消すためだけにエクスポートまたは固定された内部実装。
  • 空の可能性がある結果を走査するループ内だけのアサーション、空でないことを確認しない violations == []、テスト対象のコードから何もインポートしないテスト。
  • ソース、CSS、ワークフローのテキストを文字列として読み込んでアサートする処理、ヘルパーレベルの再試行ループ、グローバルタイムアウトの引き上げ、または isCI ? a : b による予算設定。

検証ループ

テストを作成または変更した後は、次の手順を実行します。

  1. 最も関連性の高いテストコマンドを実行します。
  2. バグ修正のための TDD を意図していた場合は、レッドの証拠とグリーンの証拠を分けて報告します。修正前の失敗する実行を確認していない場合は、TDD を完了したと主張せず、レッドフェーズは未検証とします。
  3. 変更したテストを確認し、単独で弱いアサーション、スキップ/フォーカスマーカー、アサーションを伴わないログ出力、スリープ、実ネットワークへのアクセス、実装詳細との結び付きがないか調べます。また、期待結果が SUT から独立したオラクルに基づいていること、入力の欠落/デフォルト化/入れ替わりを検出できるテスト値が少なくとも 1 つあること、関連する境界値が引き続き網羅されていること、アサーションが対象動作のフィールドに絞られていることも確認します。
  4. セキュリティ/変換のテストでは、拒否/削除と保持の両方を確認します。
  5. 不変条件に関する作業では、該当する場合、両方の手法を確認します。不変条件の証明と、不正な状態に到達できることの確認です。
  6. プロパティ/ファズテストでは、主張する入力ドメイン、独立したオラクル、エンジン標準の再生機能を確認します。また、設定によって不確実性がある場合は、正確な CI コマンドでテストの収集またはターゲット選択も確認します。
  7. 成功/失敗は出力テキストではなく終了ステータスで判断します。サブモードではなく、正確な CI エントリーポイントを実行し、変更したタグで制御されるファイルは、そのタグを指定してコンパイルします。
  8. CI を修復する場合は、「古くなったセレクターの更新」と「アサーションの弱体化またはタイムアウトの延長」を分け、弱体化する変更にはすべて理由を示します。クリーンなベースチェックアウトで再現するまでは、失敗を既存の問題と判断しません。
  9. 検証が阻まれた場合は、正確なコマンド、失敗内容、次善の確認方法を報告します。実行していないテストが通ったと主張してはいけません。成功したと報告する場合は、どの環境で確認したかを明記し、該当する場合はプッシュしたコミットの CI も確認します。

最終報告の要件

テスト作業の最後に、次を記載します。

Tests changed/assessed:
Behavior covered:
Commands run:
Results:
CI status (ran / red / not running):
TDD evidence (if claimed):
Gaps / risks:
Follow-ups:

簡潔にまとめつつ、検証内容と残るリスクを後から確認できるようにします。

コメント