Property-Based Test Generator
仕様に根拠のあるプロパティと入力生成戦略を設計し、既存のテスト環境で実行する。 テスト件数や自己採点を品質の代替にしない。
対象の特定
ユーザーが指定した関数・ファイル・範囲・比較元を最優先する。指定ファイルは変更の有無にかかわらず対象にし、無関係な変更まで対象を広げない。
「現在の変更」の場合はリポジトリのルートから以下を確認し、コミット済み差分、ステージ済み、未ステージ、未追跡の候補を重複なくまとめる。
- 比較元はユーザー指定、PR の base、設定されたリモートの既定ブランチの順で確認する。ローカルで
git symbolic-ref --quiet refs/remotes/<remote>/HEADなどから判定し、mainやoriginを固定しない。upstream は同じ作業ブランチの場合があるので自動的に比較元とみなさない。 - 比較元を特定できたら
git merge-base <base> HEADを求め、git diff --name-status -z --diff-filter=ACMR <merge-base> HEADでコミット済み候補を取得する。 git diff --name-status -z --diff-filter=ACMR --cached、git diff --name-status -z --diff-filter=ACMR、git ls-files --others --exclude-standard -zを併せて読む。空白・改行を含むパスに対応するため NUL 区切りで扱い、rename/copy は変更後のパスを使う。- 集約した候補は現在の作業ツリーで確認し、削除済みのファイルを除外する。まだ HEAD のないリポジトリでもステージ済み・未追跡ファイルを調べる。
- 比較元が不明なら推測せず、確定できる作業ツリーの範囲を先に調査する。コミット済み範囲の特定が必要なら不足情報を尋ね、比較できなかった範囲を明記する。
純粋関数、バリデータ、パーサ・シリアライザ、フォーマッタ、状態遷移、整列・変換処理を優先する。単純な getter や UI 描画のみなど、PBT の利益が小さい対象は理由を添えて除外する。副作用がある場合は純粋な境界を探すか、既存の隔離方法で検証可能か判断する。
仕様とプロパティの設計
入力・出力・前提条件・業務ルールを、公開仕様、既存テスト、呼び出し側から抽出する。実装をそのまま期待値に写さず、曖昧な仕様は仮定として明示する。
| プロパティ | 適用例 |
|---|---|
| 不変条件 | 要素保存、結果の範囲、整列順序 |
| 往復 | decode(encode(x)) と元の値の同値性 |
| 冪等性 | 正規化を再適用しても結果が変わらない |
| 入力変形との関係 | 入力順序を変えても集計結果が変わらない |
| 単調性 | 仕様上、入力増加で出力が減らない |
| 参照モデル | 独立した単純なモデルとの一致 |
件数の下限は設けず、仕様上の異なる失敗を検出する少数のプロパティを選ぶ。各プロパティについて対応する要件と検出できる不具合例を説明できること。型だけの検査や例外が出ないことだけで満足せず、期待する振る舞いを検証する。往復や冪等性だけでは誤った定数出力などを見逃すため、必要に応じて意味上の条件も組み合わせる。
生成戦略と実装
既存のテストランナー、設定、依存定義・ロックファイル・導入版を先に確認する。使用する言語の資料だけを読む。
- TS/JS: fast-check
- Python: Hypothesis
- Rust: proptest
参照例と導入版の API が異なる場合は、ローカルの型・ドキュメント、必要に応じて該当版の公式資料で確認する。例に合わせるためだけにライブラリを更新しない。
入力の制約は生成器の合成で表現し、filter / assume は必要な条件に限定する。空、ゼロ、境界、重複、Unicode など仕様に関係するケースを含め、確実に実行すべき境界は明示例や通常のテストにもする。サイズ・試行回数は既存設定と計算量に合わせる。縮小を維持し、過剰な棄却やタイムアウトを隠さない。
既存の配置・命名・assertion に従ってテストを書き、非同期処理を必ず待つ。通常実行で単一 seed に固定して探索範囲を狭めない。失敗時には入力、期待値、実値と、ライブラリに合った再現情報が得られるようにする。
実行と完了条件
検証観点 を使い、生成したテストを既存コマンドで実際に実行する。必要な型検査と関連テストも実行する。
失敗した場合は、生成器・テストの誤りと製品の不具合を区別する。仕様に反して期待値を緩めて通さない。得られた縮小反例と seed/path、reproduction blob、永続化ファイル等を記録し、同じ環境・版で再実行して再現を確認する。製品修正が依頼範囲外なら勝手に直さず、不具合と再現テストを報告する。
完了報告には対象と比較元、検証する仕様、変更ファイル、実行コマンドと結果、失敗時の再現手順を簡潔に含める。対象テストと必要な関連チェックの成功をもって検証済みとする。依存・環境不足や未解決不具合で実行・成功に至らない場合は、完了を装わず未検証範囲と理由を明示する。失敗がない場合、反例や seed を捏造する必要はない。