mcpField
P
property-based-testing

property-based-testing

github.com/laurigatesテスト・品質5972 回インストール今日更新
リポジトリ

property-based-testing について

固定例だけでなく、生成した入力で性質や不変条件を検証する開発者向けテストリファレンスです。TypeScript/JavaScript の fast-check と Python の Hypothesis を扱い、失敗例の縮小やステートフルテストも紹介します。

主な機能

  1. 01テスト入力の自動生成
  2. 02失敗ケースの縮小
  3. 03fast-check と Hypothesis の例
  4. 04性質・不変条件のテストパターン
  5. 05Hypothesis によるステートフルテスト

活用シーン

  1. 01エンコードとデコードの往復を検証
  2. 02データ変換の境界ケースを発見
  3. 03生成データで API 契約を検証
  4. 04不変条件に照らして操作列をテスト

インストール

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

$npx skills add https://github.com/laurigates/claude-plugins --skill property-based-testing

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

同梱ファイルREFERENCE.md

詳細

プロパティベーステスト

特定の例をテストするのではなく、コードの性質を検証するテストケースを自動生成する、プロパティベーステストの専門知識です。

このスキルを使う場面

このスキルを使う場面...代わりに別のスキルを使う場面...
数学的性質(可換性、結合性)をテストする特定の例に基づくユニットテストを書く
エンコード/デコードの往復をテストするテストランナーの設定を行う
エッジケースを自動的に見つけるE2E のブラウザーテストを行う
データ変換と不変条件を検証するテストの品質や問題点を分析する
生成データで API コントラクトをテストするミューテーションテストを実行する

主な専門分野

プロパティベーステストの概念

  • 従来のテスト:特定の例をテストします
  • プロパティベーステスト:すべての入力に対して成り立つべき性質をテストします
  • ジェネレーター:多様なテスト入力を自動的に作成します
  • シュリンキング:失敗ケースを最も単純な例に縮小します
  • カバレッジ:人間が見落とす可能性のあるエッジケースを探索します

プロパティベーステストを使う場面

  • 数学演算(可換性、結合性)
  • エンコーダー/デコーダー(往復の性質)
  • パーサーとシリアライザー
  • データ変換
  • API コントラクト
  • 不変条件と制約

TypeScript/JavaScript(fast-check)

インストール
# Using Bun
bun add -d fast-check

# Using npm
npm install -D fast-check
基本的な例
import { test } from 'vitest'
import * as fc from 'fast-check'

// Property-based test
test('reverse twice returns original - property based', () => {
  fc.assert(
    fc.property(
      fc.array(fc.integer()), // Generate random arrays of integers
      (arr) => {
        expect(reverse(reverse(arr))).toEqual(arr)
      }
    )
  )
})
// fast-check automatically generates 100s of test cases!
主なジェネレーター(クイックリファレンス)
ジェネレーター説明
fc.integer()任意の整数(最小値/最大値を指定可能)
fc.nat()自然数(>= 0)
fc.float() / fc.double()浮動小数点数
fc.string()任意の文字列(長さを指定可能)
fc.emailAddress()メールアドレス形式の文字列
fc.array(arb)任意の型の配列
fc.record({...})型付きフィールドを持つオブジェクト
fc.boolean()ブール値
fc.constantFrom(...)選択肢から選ぶ
fc.tuple(...)固定サイズのタプル
fc.oneof(...)ユニオン型
fc.option(arb)値または null
fc.date()Date オブジェクト
よくテストするプロパティ
プロパティパターン例
往復性f(g(x)) = xエンコード/デコード、シリアライズ/解析
冪等性f(f(x)) = f(x)ソート、正規化、フォーマット
可換性f(a,b) = f(b,a)加算、マージ、和集合
結合性f(f(a,b),c) = f(a,f(b,c))加算、連結
単位元f(x, id) = x1 を掛ける、0 を足す
逆演算f(g(x)) = x暗号化/復号
設定
fc.assert(property, {
  numRuns: 1000,      // Run 1000 tests (default: 100)
  seed: 42,           // Reproducible tests
  endOnFailure: true, // Stop after first failure
})
事前条件
fc.pre(b !== 0) // Skip cases where b is 0

Python(Hypothesis)

インストール
# Using uv
uv add --dev hypothesis pytest

# Optional extensions
uv add --dev hypothesis[numpy]   # NumPy strategies
uv add --dev hypothesis[django]  # Django model strategies
設定
# pyproject.toml
[tool.hypothesis]
max_examples = 200
deadline = 1000

[tool.hypothesis.profiles.dev]
max_examples = 50
deadline = 1000

[tool.hypothesis.profiles.ci]
max_examples = 500
deadline = 5000
verbosity = "verbose"
# Activate profile in conftest.py
from hypothesis import settings
settings.load_profile("ci")
基本的な例
from hypothesis import given, example, assume
import hypothesis.strategies as st

# Test a property
@given(st.integers(), st.integers())
def test_addition_commutative(a, b):
    assert a + b == b + a

# Add explicit edge cases with @example
@given(st.integers())
@example(0)
@example(-1)
@example(2**31 - 1)
def test_with_explicit_examples(x):
    assert process(x) is not None
主なストラテジー(クイックリファレンス)
ストラテジー説明
st.integers()任意の整数(範囲を指定可能)
st.floats()浮動小数点数
st.text()任意の文字列(サイズを指定可能)
st.binary()バイト文字列
st.lists(strat)指定したストラテジーのリスト
st.sets(strat)一意な値の集合
st.dictionaries(k, v)辞書
st.booleans()ブール値
st.sampled_from(...)選択肢から選ぶ
st.tuples(...)固定サイズのタプル
st.one_of(...)ユニオン型
st.emails()有効なメールアドレス
st.uuids()UUID オブジェクト
st.dates() / st.datetimes()日付/時刻の値
st.builds(Class, ...)ストラテジーからオブジェクトを構築する
設定(Settings)
from hypothesis import given, settings, strategies as st

@settings(max_examples=1000, deadline=None)
@given(st.lists(st.integers()))
def test_with_custom_settings(arr):
    assert sort(arr) == sorted(arr)
前提条件
from hypothesis import assume
assume(b != 0)  # Skip cases where b is 0
ステートフルテスト

Hypothesis は、RuleBasedStateMachine を使ったステートフルテストに対応しており、不変条件に対して一連の操作をテストできます。

CI との統合
# .github/workflows/test.yml
- name: Run hypothesis tests
  run: |
    uv run pytest \
      --hypothesis-show-statistics \
      --hypothesis-profile=ci \
      --hypothesis-seed=${{ github.run_number }}

- name: Upload hypothesis database
  uses: actions/upload-artifact@v4
  if: failure()
  with:
    name: hypothesis-examples
    path: .hypothesis/
クイックリファレンス
# Core decorators
@given(strategy)              # Generate test inputs
@example(value)               # Add explicit test case
@settings(max_examples=500)   # Configure behavior

# Key helpers
assume(condition)             # Skip invalid inputs
note(message)                 # Add debug info to failure output
target(value)                 # Guide generation toward value

エージェント向けの最適化

コンテキストコマンド
TS テストを素早く実行bunx vitest --dots --bail=1 --grep 'property'
Python テストを素早く実行uv run pytest -x -q --tb=short -k 'property'
CI TS テストbunx vitest run --reporter=junit --grep 'property'
CI Python テストuv run pytest --hypothesis-profile=ci --hypothesis-show-statistics -q
再現可能なテストfc.assert(prop, { seed: 42 }) または pytest --hypothesis-seed=42
高速な反復fc.assert(prop, { numRuns: 50 }) または pytest --hypothesis-profile=dev -x
失敗のデバッグpytest -x -s --hypothesis-verbosity=debug
縮小を無効化@settings に phases=[Phase.generate] を追加

詳しい例、高度なパターン、ベストプラクティスについては、REFERENCE.md を参照してください。

関連項目

  • vitest-testing - 単体テスト用フレームワーク
  • python-testing - Python の pytest テスト
  • test-quality-analysis - テストの不適切なパターンを検出
  • mutation-testing - テストの有効性を検証

参考資料

コメント