Claude-skill-registry hypothesis
Use Hypothesis for property-based testing to automatically generate comprehensive test cases, find edge cases, and write more robust tests with minimal example shrinking. Includes Polars parametric testing integration.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/hypothesis" ~/.claude/skills/majiayu000-claude-skill-registry-hypothesis && rm -rf "$T"
skills/data/hypothesis/SKILL.mdHypothesis - Property-Based Testing
Property-based testing framework that generates test cases automatically, finds minimal failing examples through shrinking, and verifies invariants.
Official Docs: https://hypothesis.readthedocs.io/en/latest/
Key Features:
- Automatic test data generation from strategies
- Minimal failing example shrinking
- Stateful testing with rule-based state machines
- pytest integration
- Deterministic reproducibility
Quick Start
from hypothesis import given from hypothesis import strategies as st @given(st.integers()) def test_property(x): """Test properties that should always hold""" assert abs(x) >= 0 @given(st.lists(st.integers())) def test_list_property(lst): sorted_lst = sorted(lst) assert len(sorted_lst) == len(lst) # Check monotonic property for i in range(len(sorted_lst) - 1): assert sorted_lst[i] <= sorted_lst[i + 1]
Strategies
Full reference: https://hypothesis.readthedocs.io/en/latest/data.html
Common strategies:
- Primitives:
,st.integers()
,st.floats()
,st.text()st.booleans() - Collections:
,st.lists()
,st.dictionaries()
,st.tuples()st.sets() - Dates/Times:
,st.dates()
,st.datetimes()st.timedeltas() - Combinators:
,st.one_of()
,st.sampled_from()st.recursive() - Type-based:
st.from_type(MyClass)
Composite Strategies
from hypothesis import strategies as st from hypothesis.strategies import composite @composite def user_strategy(draw): age = draw(st.integers(min_value=18, max_value=100)) name = draw(st.text(min_size=1)) return {"name": name, "age": age, "is_adult": age >= 18} @given(user_strategy()) def test_user(user): assert user["is_adult"] == (user["age"] >= 18)
Strategy Combinators
st.integers().filter(lambda x: x % 2 == 0) # Filter st.integers().map(str) # Transform st.one_of(st.integers(), st.text()) # Choose between strategies st.sampled_from([1, 2, 3, 4, 5]) # Pick from collection st.from_type(MyClass) # Infer from type hints st.builds(MyClass, arg1=st.integers()) # Build instances
Settings
from hypothesis import given, settings from hypothesis import strategies as st @given(st.integers()) @settings( max_examples=1000, # Default: 100 deadline=None, # Remove time limit derandomize=True, # Deterministic ordering ) def test_example(x): pass # Profiles for different environments settings.register_profile("dev", max_examples=10) settings.register_profile("ci", max_examples=1000, deadline=None) # Activate: HYPOTHESIS_PROFILE=ci pytest
Full settings reference: https://hypothesis.readthedocs.io/en/latest/settings.html
Helpers
from hypothesis import given, assume, note, example, seed @given(st.integers(), st.integers()) def test_division(x, y): assume(y != 0) # Skip invalid cases (prefer .filter() instead) note(f"Testing {x} / {y}") # Add debug info assert (x / y) * y == x @given(st.integers()) @example(0) # Always test specific cases @seed(12345) # Reproducible run def test_something(x): pass
Stateful Testing
For testing complex stateful systems with rule-based state machines.
from hypothesis.stateful import RuleBasedStateMachine, rule, invariant from hypothesis import strategies as st class MyStateMachine(RuleBasedStateMachine): def __init__(self): super().__init__() self.data = [] @rule(value=st.integers()) def add(self, value): self.data.append(value) @invariant() def check_invariant(self): assert isinstance(self.data, list) TestMachine = MyStateMachine.TestCase
Full stateful testing guide: https://hypothesis.readthedocs.io/en/latest/stateful.html
Polars Integration
Polars provides built-in parametric testing strategies for generating DataFrames.
Official docs: https://docs.pola.rs/api/python/stable/reference/api/polars.testing.parametric.dataframes.html
from hypothesis import given import polars as pl from polars.testing.parametric import dataframes, column # Generate DataFrames with specific column schemas @given( dataframes( cols=[ column("id", dtype=pl.Int64), column("name", dtype=pl.String), column("value", dtype=pl.Float64), ], min_size=1, max_size=100, ) ) def test_dataframe_property(df: pl.DataFrame): """Test properties of DataFrame operations""" assert df.shape[0] >= 1 assert set(df.columns) == {"id", "name", "value"} assert df["id"].dtype == pl.Int64 # With Narwhals wrapper import narwhals as nw @given(dataframes(cols=[column("a", dtype=pl.Int64)])) def test_narwhals_operation(df: pl.DataFrame): nw_df = nw.from_native(df) result = nw_df.select(nw.col("a") * 2) assert result.shape[0] == nw_df.shape[0]
Key functions:
: Generate DataFrames with specified columnsdataframes()
: Define column schemas with constraintscolumn(name, dtype, ...)
: Generate standalone Seriesseries()
Column constraints:
: Control null value frequencynull_probability
/min_size
: Control row countmax_size
: Enable/disable nullsallow_null
: Generate unique valuesunique
: Custom strategy for column valuesstrategy
Best Practices
- Use constraints over filters:
notst.integers(min_value=0)st.integers().filter(lambda x: x >= 0) - Test properties, not examples: Focus on invariants that always hold
- Combine with
: Test specific edge cases explicitly@example() - Avoid
overuse: Makes tests slow; use filtered strategiesassume() - Document properties: Clear docstrings explain what invariant is tested
- Set size limits: Always bound collection sizes to prevent memory issues
- Use
in.hypothesis/
: Stores example database locally.gitignore
Troubleshooting
Common issues and solutions:
- HealthCheck failures: Too many rejected examples → use constrained strategies or
suppress_health_check - Flaky tests: Non-deterministic code → use
or@seed()@settings(derandomize=True) - Slow tests: Too many examples → reduce
or use profilesmax_examples - Deadline exceeded: Complex operations → increase
or set todeadlineNone
Resources
- Main docs: https://hypothesis.readthedocs.io/
- Strategies: https://hypothesis.readthedocs.io/en/latest/data.html
- Stateful testing: https://hypothesis.readthedocs.io/en/latest/stateful.html
- Ghost writer (auto-generate tests):
hypothesis write mymodule.myfunction