hypothesis-testing

Hypothesis Property-Based Testing

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "hypothesis-testing" with this command: npx skills add laurigates/claude-plugins/laurigates-claude-plugins-hypothesis-testing

Hypothesis Property-Based Testing

Automatically generate test cases to find edge cases and validate properties of your code.

When to Use Hypothesis vs Example-Based Tests

Use Hypothesis when... Use example-based tests when...

Testing mathematical properties (commutative, associative) Testing specific known edge cases

Many valid inputs need testing Exact business logic with known values

Verifying serialization round-trips Testing specific error messages

Finding edge cases you can't predict Integration with external systems

Testing APIs with many parameters Testing UI behavior

Installation

uv add --dev hypothesis pytest

Optional extensions

uv add --dev hypothesis[numpy] # NumPy strategies uv add --dev hypothesis[django] # Django model strategies

Configuration

pyproject.toml

[tool.hypothesis] max_examples = 200 deadline = 1000

[tool.hypothesis.profiles.dev] max_examples = 50 deadline = 1000

[tool.hypothesis.profiles.ci] max_examples = 500 deadline = 5000 verbosity = "verbose"

Activate profile

from hypothesis import settings, Phase settings.load_profile("ci") # Use in conftest.py

Basic Usage

from hypothesis import given, example, assume import hypothesis.strategies as st

Test a property

@given(st.integers(), st.integers()) def test_addition_commutative(a, b): assert a + b == b + a

Add explicit edge cases

@given(st.integers()) @example(0) @example(-1) @example(2**31 - 1) def test_with_explicit_examples(x): assert process(x) is not None

Skip invalid inputs

@given(st.floats(allow_nan=False, allow_infinity=False), st.floats(allow_nan=False, allow_infinity=False)) def test_safe_divide(a, b): assume(b != 0) result = a / b assert isinstance(result, float)

Essential Strategies

import hypothesis.strategies as st

Primitives

st.integers() # Any integer st.integers(min_value=0, max_value=100) # Bounded st.floats(allow_nan=False) # Floats without NaN st.booleans() # True/False st.text() # Unicode strings st.text(min_size=1, max_size=50) # Bounded strings st.binary() # Bytes

Collections

st.lists(st.integers()) # List of ints st.lists(st.text(), min_size=1) # Non-empty list st.dictionaries(st.text(), st.integers()) # Dict st.tuples(st.integers(), st.text()) # Fixed tuple

Special types

st.emails() # Valid emails st.uuids() # UUID objects st.datetimes() # datetime objects

Choices

st.sampled_from(["a", "b", "c"]) # Pick from list st.one_of(st.integers(), st.text()) # Union type st.none() | st.integers() # Optional int

Custom Composite Strategies

from hypothesis.strategies import composite

@composite def users(draw): return { "id": draw(st.integers(min_value=1)), "name": draw(st.text(min_size=1, max_size=50)), "email": draw(st.emails()), "active": draw(st.booleans()) }

@given(users()) def test_user_validation(user): assert user["id"] > 0 assert "@" in user["email"]

From Type Annotations

from hypothesis import given from hypothesis.strategies import from_type from dataclasses import dataclass

@dataclass class Config: name: str port: int debug: bool

@given(from_type(Config)) def test_config(config: Config): assert isinstance(config.name, str) assert isinstance(config.port, int)

Common Property Patterns

1. Round-trip (encode/decode)

@given(st.text()) def test_json_roundtrip(data): assert json.loads(json.dumps(data)) == data

2. Idempotency (applying twice = applying once)

@given(st.lists(st.integers())) def test_sort_idempotent(items): assert sorted(sorted(items)) == sorted(items)

3. Invariant preservation

@given(st.lists(st.integers())) def test_sort_preserves_length(items): assert len(sorted(items)) == len(items)

4. Oracle (compare implementations)

@given(st.integers(min_value=0, max_value=20)) def test_fibonacci(n): assert fast_fib(n) == slow_fib(n)

CI Integration

.github/workflows/test.yml

  • name: Run hypothesis tests run: | uv run pytest
    --hypothesis-show-statistics
    --hypothesis-profile=ci
    --hypothesis-seed=${{ github.run_number }}

  • name: Upload hypothesis database uses: actions/upload-artifact@v4 if: failure() with: name: hypothesis-examples path: .hypothesis/

Agentic Optimizations

Context Command

Quick check pytest -x --hypothesis-seed=0 -q

Fail fast pytest --hypothesis-profile=dev -x --tb=short

CI mode pytest --hypothesis-profile=ci --hypothesis-show-statistics

Reproducible pytest --hypothesis-seed=42

Debug failing pytest -x -s --hypothesis-verbosity=debug

No shrinking Add phases=[Phase.generate] to @settings

Quick Reference

Core decorators

@given(strategy) # Generate test inputs @example(value) # Add explicit test case @settings(max_examples=500) # Configure behavior

Key settings

assume(condition) # Skip invalid inputs note(message) # Add debug info to failure target(value) # Guide generation toward value

For advanced patterns (stateful testing, recursive data, settings), best practices, and debugging guides, see REFERENCE.md.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

ruff-linting

No summary provided by upstream source.

Repository SourceNeeds Review
General

imagemagick-conversion

No summary provided by upstream source.

Repository SourceNeeds Review
General

jq json processing

No summary provided by upstream source.

Repository SourceNeeds Review