property-based-testing
SKILL.md
Property-Based Testing
Expert knowledge for property-based testing - automatically generating test cases to verify code properties rather than testing specific examples.
When to Use This Skill
| Use this skill when... | Use another skill instead when... |
|---|---|
| Testing mathematical properties (commutative, associative) | Writing specific example-based unit tests |
| Testing encode/decode roundtrips | Setting up test runner configuration |
| Finding edge cases automatically | Doing E2E browser testing |
| Validating data transformations and invariants | Analyzing test quality or smells |
| Testing API contracts with generated data | Running mutation testing |
Core Expertise
Property-Based Testing Concept
- Traditional testing: Test specific examples
- Property-based testing: Test properties that should hold for all inputs
- Generators: Automatically create diverse test inputs
- Shrinking: Minimize failing cases to simplest example
- Coverage: Explore edge cases humans might miss
When to Use Property-Based Testing
- Mathematical operations (commutative, associative properties)
- Encoders/decoders (roundtrip properties)
- Parsers and serializers
- Data transformations
- API contracts
- Invariants and constraints
TypeScript/JavaScript (fast-check)
Installation
# Using Bun
bun add -d fast-check
# Using npm
npm install -D fast-check
Basic Example
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!
Key Generators (Quick Reference)
| Generator | Description |
|---|---|
fc.integer() |
Any integer (with optional min/max) |
fc.nat() |
Natural numbers (>= 0) |
fc.float() / fc.double() |
Floating-point numbers |
fc.string() |
Any string (with optional length) |
fc.emailAddress() |
Email format strings |
fc.array(arb) |
Arrays of arbitrary type |
fc.record({...}) |
Object with typed fields |
fc.boolean() |
Boolean values |
fc.constantFrom(...) |
Pick from options |
fc.tuple(...) |
Fixed-size tuples |
fc.oneof(...) |
Union types |
fc.option(arb) |
Value or null |
fc.date() |
Date objects |
Common Properties to Test
| Property | Pattern | Example |
|---|---|---|
| Roundtrip | f(g(x)) = x |
encode/decode, serialize/parse |
| Idempotence | f(f(x)) = f(x) |
sort, normalize, format |
| Commutativity | f(a,b) = f(b,a) |
add, merge, union |
| Associativity | f(f(a,b),c) = f(a,f(b,c)) |
add, concat |
| Identity | f(x, id) = x |
multiply by 1, add 0 |
| Inverse | f(g(x)) = x |
encrypt/decrypt |
Configuration
fc.assert(property, {
numRuns: 1000, // Run 1000 tests (default: 100)
seed: 42, // Reproducible tests
endOnFailure: true, // Stop after first failure
})
Preconditions
fc.pre(b !== 0) // Skip cases where b is 0
Python (Hypothesis)
Installation
# Using uv
uv add --dev hypothesis
# Using pip
pip install hypothesis
Basic Example
from hypothesis import given, strategies as st
@given(st.lists(st.integers()))
def test_reverse_twice_property(arr):
assert reverse(reverse(arr)) == arr
# Hypothesis automatically generates 100s of test cases!
Key Strategies (Quick Reference)
| Strategy | Description |
|---|---|
st.integers() |
Any integer (with optional bounds) |
st.floats() |
Floating-point numbers |
st.text() |
Any string (with optional size) |
st.binary() |
Byte strings |
st.lists(strat) |
Lists of given strategy |
st.sets(strat) |
Unique value sets |
st.dictionaries(k, v) |
Dictionaries |
st.booleans() |
Boolean values |
st.sampled_from(...) |
Pick from options |
st.tuples(...) |
Fixed-size tuples |
st.one_of(...) |
Union types |
st.dates() / st.datetimes() |
Date/time values |
st.builds(Class, ...) |
Build objects from strategies |
Configuration
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)
Assumptions
from hypothesis import assume
assume(b != 0) # Skip cases where b is 0
Stateful Testing
Hypothesis supports stateful testing via RuleBasedStateMachine for testing sequences of operations against invariants.
Agentic Optimizations
| Context | Command |
|---|---|
| Quick TS test | bunx vitest --dots --bail=1 --grep 'property' |
| Quick Python test | uv run pytest -x -q --tb=short -k 'property' |
| CI TS test | bunx vitest run --reporter=junit --grep 'property' |
| CI Python test | uv run pytest --hypothesis-show-statistics -q |
| Reproducible | fc.assert(prop, { seed: 42 }) or @settings(derandomize=True) |
| Fast iteration | fc.assert(prop, { numRuns: 50 }) or @settings(max_examples=50) |
For detailed examples, advanced patterns, and best practices, see REFERENCE.md.
See Also
vitest-testing- Unit testing frameworkpython-testing- Python pytest testingtest-quality-analysis- Detecting test smellsmutation-testing- Validate test effectiveness
References
- fast-check: https://fast-check.dev/
- Hypothesis: https://hypothesis.readthedocs.io/
- Property-Based Testing: https://fsharpforfunandprofit.com/posts/property-based-testing/
Weekly Installs
48
Repository
laurigates/clau…-pluginsGitHub Stars
13
First Seen
Jan 29, 2026
Security Audits
Installed on
github-copilot47
opencode47
amp46
codex46
kimi-cli46
gemini-cli46