Loading...
Loading...
Property-based testing with Hypothesis for discovering edge cases automatically. Use when testing invariants, finding boundary conditions, implementing stateful testing, or validating data transformations.
npx skill4agent add yonatangross/orchestkit property-based-testing# Example-based: Test specific inputs
def test_sort_examples():
assert sort([3, 1, 2]) == [1, 2, 3]
# But what about [-1], [1.5, 2.5], ...?
# Property-based: Test properties for ALL inputs
from hypothesis import given
from hypothesis import strategies as st
@given(st.lists(st.integers()))
def test_sort_properties(lst):
result = sort(lst)
assert len(result) == len(lst) # Same length
assert all(result[i] <= result[i+1] for i in range(len(result)-1)) # Orderedfrom hypothesis import strategies as st
st.integers(min_value=0, max_value=100) # Bounded integers
st.text(min_size=1, max_size=50) # Bounded text
st.lists(st.integers(), max_size=10) # Bounded lists
st.from_regex(r"[a-z]+@[a-z]+\.[a-z]+") # Pattern-based
# Composite for domain objects
@st.composite
def user_strategy(draw):
return User(
name=draw(st.text(min_size=1, max_size=50)),
age=draw(st.integers(min_value=0, max_value=150)),
)# Roundtrip (encode/decode)
@given(st.dictionaries(st.text(), st.integers()))
def test_json_roundtrip(data):
assert json.loads(json.dumps(data)) == data
# Idempotence
@given(st.text())
def test_normalize_idempotent(text):
assert normalize(normalize(text)) == normalize(text)
# Oracle (compare to known implementation)
@given(st.lists(st.integers()))
def test_sort_matches_builtin(lst):
assert our_sort(lst) == sorted(lst)| Decision | Recommendation |
|---|---|
| Strategy design | Composite strategies for domain objects |
| Example count | 100 for CI, 10 for dev, 1000 for release |
| Database tests | Use explicit mode, limit examples |
| Deadline | Disable for slow tests, 200ms default |
| Stateful tests | RuleBasedStateMachine for state machines |
# NEVER ignore failing examples
@given(st.integers())
def test_bad(x):
if x == 42:
return # WRONG - hiding failure!
# NEVER use filter with low hit rate
st.integers().filter(lambda x: x % 1000 == 0) # WRONG - very slow
# NEVER test with unbounded inputs
@given(st.text()) # WRONG - includes 10MB strings
def test_username(name):
User(name=name)
# NEVER mutate strategy results
@given(st.lists(st.integers()))
def test_mutating(lst):
lst.append(42) # WRONG - mutates generated datapytest-advancedunit-testingcontract-testing