Testing¶
Soft assertions¶
By default a failure halts the test immediately. Soft assertions collect failures and raise them together at the end, so one run reports every problem:
from assertpy2 import assert_that, soft_assertions
with soft_assertions():
assert_that("foo").is_length(4)
assert_that("foo").is_empty()
assert_that("foo").is_equal_to("bar")
Collected failures raised at the end of the block
Note
Only assertion failures are collected. Errors like TypeError/ValueError and an explicit fail()
halt immediately; use soft_fail() to collect a forced failure. Soft state is thread-safe and
async-safe (independent per thread and per asyncio.Task via contextvars).
Grouped soft assertions¶
Bind the collector with as sa and group failures by section with sa.group(label):
with soft_assertions() as sa:
with sa.group("Headers"):
assert_that(headers["Content-Type"]).is_equal_to("application/json")
with sa.group("Body"):
assert_that(body["status"]).is_equal_to("ok")
Grouped output
assert_all¶
A convenience wrapper for inline soft assertions, equivalent to wrapping the calls in
with soft_assertions()::
from assertpy2 import assert_all, assert_that
assert_all(
lambda: assert_that(x).is_positive(),
lambda: assert_that(y).is_not_none(),
lambda: assert_that(z).is_length(3),
)
Async assertions¶
eventually() creates a polling assertion that retries until the condition holds or a timeout is
reached, useful for eventual consistency and reactive systems:
By default it polls for 5 seconds every 0.5 seconds; tune with within() and every():
Both sync and async callables work, and any assertion method is available after eventually():
await assert_that(async_get_status).eventually().is_equal_to("done")
await assert_that(get_name).eventually().starts_with("Al")
await assert_that(get_count).eventually().is_between(10, 20)
Note
Only AssertionError is retried; other exceptions propagate immediately. On timeout the last
AssertionError is chained for context.
Snapshot testing¶
Capture a data structure to disk as JSON and compare against it on every run. Borrowed from Jest.
On the first run the snapshot file is created and the test passes; on later runs the value is compared
to the stored snapshot and the test fails on any mismatch. Most Python structures are supported
(dict, list, set, objects, numbers, None, complex). Commit snapshot artifacts (the
__snapshots folder) to source control.
Updating snapshots¶
Delete the snapshot files and re-run the suite to regenerate them.
Parameters¶
Snapshots are keyed by test filename plus line number by default; override with id or path: