Generates **property-based tests** that use randomized input generation to validate invariants and contracts (rather than hand-picked examples). Triggers when the conversation involves: PBT frameworks (Hypothesis library for Python, fast-check for TypeScript, proptest for Rust, rapid for Go, RapidCheck for C++); concepts like invariants, contracts, round-trip symmetry, encode/decode, serialize/deserialize, generative testing, or shrinking; or requests to find edge cases that example-based tests miss — e.g., "find edge cases automatically", "test all possible inputs", "verify this property holds". Does NOT trigger for: writing regular example-based unit tests, debugging, CI/CD setup, UI/component testing, or integration/E2E testing. Identifies up to 7 property patterns (round-trip, idempotence, invariance, metamorphic, inverse, ordering, no-crash), designs input generators, writes property tests, and extracts regression tests from failures.
91
90%
Does it follow best practices?
Impact
94%
1.11xAverage score across 5 eval scenarios
Passed
No known issues
Dependency: pip install hypothesis (add pytest for running tests)
from hypothesis import given, assume, strategies as stst.integers() # Any integer
st.integers(min_value=0, max_value=100) # Constrained
st.floats() # Any float (includes NaN, inf)
st.floats(allow_nan=False) # Finite floats only
st.text() # Any string (including empty)
st.text(alphabet="abc", min_size=1) # Strings from a specific alphabet
st.booleans() # True or False
st.none() # Always None
st.just(42) # Always 42 (constant)
st.sampled_from(["a", "b"]) # Pick randomly from a list
st.lists(st.integers()) # Lists of integers
st.lists(st.integers(), min_size=1, max_size=10) # Sized lists
st.dictionaries(st.text(), st.integers()) # Dicts
st.tuples(st.text(), st.integers()) # Tuples
st.one_of([st.none(), st.text()]) # Union types
st.builds(MyClass, name=st.text(), age=st.integers(0, 120)) # Construct objects@given(st.lists(st.integers()))
def test_sort_length_invariant(lst):
original_len = len(lst)
result = sorted(lst)
assert len(result) == original_len
@given(st.lists(st.integers()))
def test_sort_ordered(lst):
result = sorted(lst)
for i in range(len(result) - 1):
assert result[i] <= result[i + 1]assumeSkip invalid input combinations:
@given(st.integers(), st.integers())
def test_divide(a, b):
assume(b != 0)
assert a / b * b == a # Approximateclass User:
def __init__(self, name, age):
self.name = name
self.age = age
@given(st.builds(User,
name=st.text(min_size=1, max_size=50),
age=st.integers(min_value=0, max_value=150)))
def test_user_properties(user):
assert len(user.name) > 0.map() and .filter()# Map: transform generated values
even_ints = st.integers().map(lambda x: x * 2)
# Filter: only keep values matching predicate
nonzero = st.integers().filter(lambda x: x != 0)
# Combine
positive_evens = st.integers(min_value=1).map(lambda x: x * 2)from hypothesis import given, strategies as st
@given(st.integers())
def test_divide_by_zero_raises(x):
assume(x != 0)
with pytest.raises(ZeroDivisionError):
1 / (x - x) # This will always fail since we assume x != 0from hypothesis import settings
@given(st.lists(st.integers()))
@settings(max_examples=500) # Default is 100
def test_with_more_iterations(lst):
...
@given(st.lists(st.integers()))
@settings(max_examples=10) # Fast check for CI
def test_quick(lst):
...When Hypothesis reports a failure, it gives you a seed:
Falsifying example: test_sort(
lst=[3, 1, 2],
)Use @seed(42) or --hypothesis-seed=42 to reproduce:
from hypothesis import seed
@given(st.lists(st.integers()))
@seed(12345)
def test_sort_reproducible(lst):
...pytest test_stock.py -v # All tests
pytest test_stock.py -k "property" -v # Filter by name
pytest --hypothesis-show-statistics # Show generated value statsHypothesis saves failing examples in .hypothesis/examples/. This means failures from a previous run are replayed on subsequent runs — you don't lose found bugs.