Use when writing tests for serialization, validation, normalization, or pure functions - provides property catalog, pattern detection, and library reference for property-based testing
Property-based testing (PBT) generates random inputs and verifies that properties hold for all of them. Instead of testing specific examples, you test invariants.
When PBT beats example-based tests:
| Property | Formula | When to Use |
|----------|---------|-------------|
| Roundtrip | decode(encode(x)) == x | Serialization, conversion pairs |
| Idempotence | f(f(x)) == f(x) | Normalization, formatting, sorting |
| Invariant | Property holds before/after | Any transformation |
| Commutativity | f(a, b) == f(b, a) | Binary/set operations |
| Associativity | f(f(a,b), c) == f(a, f(b,c)) | Combining operations |
| Identity | f(x, identity) == x | Operations with neutral element |
| Inverse | f(g(x)) == x | encrypt/decrypt, compress/decompress |
| Oracle | new_impl(x) == reference(x) | Optimization, refactoring |
| Easy to Verify | is_sorted(sort(x)) | Complex algorithms |
| No Exception | No crash on valid input | Baseline (weakest) |
Strength hierarchy (weakest to strongest):
No Exception -> Type Preservation -> Invariant -> Idempotence -> Roundtrip
Always aim for the strongest property that applies.
Use PBT when you see:
| Pattern | Property | Priority |
|---------|----------|----------|
| encode/decode, serialize/deserialize | Roundtrip | HIGH |
| toJSON/fromJSON, pack/unpack | Roundtrip | HIGH |
| Pure functions with clear contracts | Multiple | HIGH |
| normalize, sanitize, canonicalize | Idempotence | MEDIUM |
| is_valid, validate with normalizers | Valid after normalize | MEDIUM |
| Sorting, ordering, comparators | Idempotence + ordering | MEDIUM |
| Custom collections (add/remove/get) | Invariants | MEDIUM |
| Builder/factory patterns | Output invariants | LOW |
| Language | Library | Import |
|----------|---------|--------|
| Python | Hypothesis | from hypothesis import given, strategies as st |
| TypeScript/JS | fast-check | import fc from 'fast-check' |
| Rust | proptest | use proptest::prelude::* |
| Go | rapid | import "pgregory.net/rapid" |
| Java | jqwik | @Property annotations |
| Haskell | QuickCheck | import Test.QuickCheck |
For library-specific syntax and patterns: Use @ed3d-research-agents:internet-researcher to get current documentation.
Constrain early: Build constraints INTO the strategy, not via assume()
# GOOD
st.integers(min_value=1, max_value=100)
# BAD - high rejection rate
st.integers().filter(lambda x: 1 <= x <= 100)
Size limits: Prevent slow tests
st.lists(st.integers(), max_size=100)
st.text(max_size=1000)
Realistic data: Match real-world constraints
st.integers(min_value=0, max_value=150) # Real ages, not arbitrary ints
Reuse strategies: Define once, use across tests
valid_users = st.builds(User, ...)
@given(valid_users)
def test_one(user): ...
@given(valid_users)
def test_two(user): ...
# Development (fast feedback)
@settings(max_examples=10)
# CI (thorough)
@settings(max_examples=200)
# Nightly/Release (exhaustive)
@settings(max_examples=1000, deadline=None)
Before committing PBT tests:
assume())@example)assert sorted(xs) == sorted(xs) tests nothingassume() calls filter out most inputsassert add(a, b) == a + b if that's how add is implemented@example([]), @example([1]) decoratorsassume() calls means redesign the strategy| Mistake | Fix | |---------|-----| | Testing mock behavior | Test real behavior | | Reimplementing function in test | Use algebraic properties | | Filtering with assume() | Build constraints into strategy | | No edge case examples | Add @example decorators | | One property only | Add multiple properties (length, ordering, etc.) |
npx skills add ed3dai/property-based-testing下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer