SqlProof Class
SqlProof is the entry point for a test suite. Create one instance from a schema file,
connection string, or config object, then use @sqlproof, check(), or invariant().
Constructors
Section titled “Constructors”For explicit configuration:
Exactly one of schema_file or connection_string must be provided.
Decorator Usage
Section titled “Decorator Usage”Imperative Usage
Section titled “Imperative Usage”Invariants
Section titled “Invariants”Use invariant() when a SQL query should return zero rows (or, with
expect_empty=False, at least one row) for every generated dataset.
Each run loads a generated dataset into the database inside a savepoint, executes
query, and rolls the savepoint back. If the query returns rows when
expect_empty=True (or none when expect_empty=False), invariant() raises
SqlProofPropertyFailure with the dataset as the counterexample. Errors from
the database, such as an unknown table or a syntax error, are raised as-is and
never count as a pass.
Pass seed=1234 to check() or invariant() to repeat a search with the
same schema, strategies and dependency versions. An explicit seed disables
Hypothesis’s example database for that run. Without a seed, Hypothesis’s
normal profile and --hypothesis-seed settings apply. Failing invariants
shrink their datasets, and the exception’s counterexample includes the seed
used (or None for a derandomized run), the run that first failed and the
number of shrinking calls after it. It is also saved under
.sqlproof/failures/, as check() does.
A recorded seed repeats the random search, not necessarily the failure.
When Hypothesis replays a failure saved in its example database by an
earlier run, the seed of the current run never searched for it, and passing
it back turns the database off. Keep the .hypothesis/ directory or the
counterexample file to reproduce such a failure. Each property and
invariant has its own example-database entry, so one passing property
never discards another’s saved failure.
invariant() needs a database connection (from_connection_string) to run
arbitrary SQL. A proof built only from a schema file evaluates queries in
memory, which handles just a plain SELECT <columns> FROM <table>. Any other
query, including one with a WHERE clause or a JOIN like the example below,
raises SqlProofUsageError instead of being evaluated with its predicates
ignored.
External Tables
Section titled “External Tables”When your schema has FKs into a table SqlProof shouldn’t generate (e.g.
Supabase’s auth.users), register an ExternalTableSpec so the generator
samples FK values from the live external parent:
See the Supabase guide for a full walkthrough.
Stateful tests
Section titled “Stateful tests”For invariants that only surface across sequences of mutations
(pagination, windowed aggregates, RLS membership churn), use a state
machine via proof.run_state_machine:
See the stateful testing API for details.
Cleanup
Section titled “Cleanup”SqlProof is a context manager: