hypothesis

Property-based testing for Python that generates edge cases and shrinks failures to their simplest reproducing example.

Library
PyPI
v6.167.1
8,941stars
Mozilla Public License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
90/100Excellent
Development Activity100
Maintenance96
Community64
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
91/100Excellent
Architecture93
Code Quality92
Innovation88
Learning Curve90

Hypothesis is the property-based testing library for Python. Instead of writing individual example-based test cases, you describe the space of valid inputs with composable strategies, and Hypothesis generates hundreds of randomized inputs per test run — including boundary values and edge cases a human tester is unlikely to think of. When a test fails, Hypothesis doesn’t just report the first failing input; it runs a shrinking process that reduces the failing example down to the smallest, simplest input that still reproduces the bug, making the root cause far easier to diagnose.

Under the hood, the library is built around a “conjecture” engine that generates and mutates raw choice sequences, which strategies then interpret into typed Python values (integers, lists, floats, dates, custom objects, and more). This separation between the low-level choice-generation engine and the high-level strategy layer lets Hypothesis apply the same shrinking and mutation logic uniformly across every data type, and lets it persist a database of previously-found failing examples so regressions are caught immediately on the next run.

Hypothesis integrates directly as a pytest plugin (and works with unittest and Django’s test runner), ships a stateful-testing API for modeling sequences of operations against rule-based state machines, and includes optional extras for NumPy, pandas, Django, dateutil, lark-based grammar fuzzing, and a Ghostwriter that scaffolds property-based tests from a function’s type signature. A Rust-based native extension (via PyO3/maturin) accelerates hot paths like floating-point interval arithmetic.

What You Get

  • A @given decorator that turns a normal test function into a property-based test driven by generated inputs
  • A large library of built-in strategies (integers, floats, text, lists, dates, UUIDs, JSON-like recursive structures, and more) that compose into arbitrarily complex generators
  • Automatic shrinking that reduces any failing example to the smallest input that still reproduces the failure
  • A local example database that persists previously-found failures so regressions are caught immediately on future runs
  • Stateful testing support (RuleBasedStateMachine) for modeling and fuzzing sequences of operations against stateful systems
  • A Ghostwriter that generates draft property-based tests automatically from a function’s type signature
  • First-class integrations for pytest, unittest, Django, NumPy, pandas, and dateutil via optional extras

Common Use Cases

  • Testing pure functions and algorithms (parsers, serializers, sort/search routines) against a much wider input space than hand-written examples cover
  • Finding edge cases in numeric code — float precision issues, off-by-one boundaries, overflow — that example-based tests routinely miss
  • Fuzzing API and data-validation layers by generating malformed or boundary-case JSON, strings, and structured payloads
  • Stateful/model-based testing of stateful systems (databases, caches, protocol implementations) by generating sequences of valid operations
  • Regression testing where previously-discovered failing inputs are replayed automatically via the persisted example database

Under The Hood

Architecture Hypothesis is layered around a “conjecture” engine (hypothesis/internal/conjecture/) that generates, mutates, and shrinks raw sequences of low-level choices (choice.py, data.py, engine.py, shrinker.py, datatree.py); the higher-level strategies package interprets those choice sequences into typed Python values, so every strategy — from simple integers to recursive user-defined structures — reuses the same generation, caching, and shrinking machinery instead of implementing it per type. core.py glues this engine to the public @given decorator and test-runner integrations (pytest, unittest, Django), handling settings resolution, health checks, deadline enforcement, and flaky-test detection. This separation of a generic choice-sequence engine from type-specific strategy interpretation is what lets one shrinking algorithm serve every data type uniformly, and what would break most severely if the conjecture/strategy boundary were altered.

Tech Stack The project is pure Python 3.10+ for its public API and strategy layer, with a small Rust extension (rust/, built via PyO3 and the maturin build backend declared in pyproject.toml) accelerating hot numeric paths such as floating-point interval math. Core runtime dependencies are minimal — sortedcontainers and a backport of exceptiongroup for pre-3.11 — while a wide set of optional extras (click, black, libcst, lark, numpy, pandas, django, redis, crosshair-tool, watchdog) are pulled in only when the corresponding integration is used. Packaging and native-module builds run through maturin, and the library registers itself as a pytest11 entry point so pytest auto-discovers it without configuration.

Code Quality The tests/ directory contains 325+ test files spanning unit tests (cover/), slow/property-heavy tests (nocover/), and dedicated integration suites per optional extra (numpy/, pandas/, django/, dpcontracts/, array_api/, crosshair/, ghostwriter/, codemods/). Coverage is enforced at 100% for the core package via a strict [tool.coverage.report] fail_under = 100 configuration, and the library is fully typed (py.typed marker, pyrightconfig.json for the native module). Source files carry consistent MPL-2.0 license headers and the codebase favors explicit dataclasses and typed exceptions (errors.py) over ad-hoc exception handling, with dedicated modules for reflection-based edge cases (internal/reflection.py) and cross-version compatibility (internal/compat.py).

What Makes It Unique Unlike simpler fuzzing or example-generation tools, Hypothesis’s shrinking is not a generic “try smaller random inputs” search — it operates directly on the recorded choice sequence that produced a failure, replaying and mutating that exact sequence to find a smaller sequence that still fails, which lets it shrink arbitrarily complex, mutually-recursive strategies (including user-defined ones) without any type-specific shrinking code. Combined with the persisted example database (so every discovered failure becomes a permanent regression test) and the stateful-testing API for modeling sequences of operations, this makes it one of the few testing libraries capable of finding and minimizing failures in genuinely stateful, not just pure-function, code.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search