Migration from assertpy¶
assertpy2 is a drop-in replacement for the original
assertpy, which has been inactive since 2020 (last release
1.1). It keeps the same assert_that(...) API and adds static typing, composable matchers,
structural matching, async assertions, and structured failures. For most projects the migration is a
one-line change with no behavioral surprises.
TL;DR
On Python 3.10+, replace from assertpy import ... with from assertpy2 import ... and run your
tests. The assertions you already use carry over unchanged.
Before you start¶
- Python 3.10+ is required. The original assertpy ran on Python 2.7 and 3.x; assertpy2 targets 3.10 through 3.15. If you are on an older interpreter, upgrade Python first - this is the only hard requirement of the migration.
- No runtime dependencies on Python 3.11+. On 3.10 a single tiny backport (
typing_extensions) is pulled in automatically. The extras ([json],[allure],[behave]) stay opt-in.
Switch the import¶
If you import the module instead of its names, alias it so existing call sites keep working:
A project-wide find-and-replace of from assertpy import to from assertpy2 import is usually the
entire migration.
Automate it across a project
grep -rl --include="*.py" "assertpy" . \
| xargs sed -i 's/from assertpy import/from assertpy2 import/g'
from assertpy import lines. For
import assertpy usages, prefer the alias shown above.
What stays the same¶
assertpy2 is a superset of the original, so the assertions you already use are present and produce the same results:
- the
assert_that()entry point and fluent (return self) chaining; - strings, numbers, lists, tuples, dicts, sets, booleans,
None, dates, files, and objects; - dynamic
has_<name>()assertions andextracting()withfilterandsort; - soft assertions, expected exceptions (
raises().when_called_with()),fail(),assert_warn(), snapshot testing, andadd_extension(); - the existing failure messages.
Backward-compatible failures
Failing assertions now raise AssertionFailure, a subclass of AssertionError. Existing
except AssertionError handlers keep working unchanged; the subclass simply carries extra
structured data.
What improves automatically¶
You get these the moment you switch, without touching any test code:
- Thread-safe and async-safe soft assertions. State is isolated per thread and per
asyncio.Taskviacontextvars, so soft assertions are safe underpytest-xdistandasyncio. The original's soft assertions were not thread-safe. - Structured failures and rich diffs. Failures carry
.actual/.expected/.diff, and the auto-registered pytest plugin renders recursive diffs for lists, dicts, dataclasses, namedtuples, and Pydantic models. Setassertpy2_diff = "off"if you prefer the plain message. - Static typing. With
py.typedand@overloadprotocols your editor filters autocomplete by the value's type, and a type checker flags misuse before the tests run - see Type Safety.
What you can now adopt¶
New capabilities the original never had, ready whenever you want them:
- Composable matchers usable in
.satisfies(),.each(), and plain==. - Structural matching for API-response shapes.
- The collection pipeline and universal negation.
- Async polling with
eventually(). - JSON Path / Schema, regex group extraction, and bytes assertions.
See the comparison for the full feature delta.
Steps¶
- Ensure the project runs on Python 3.10+.
- Swap the dependency: uninstall
assertpy, installassertpy2, and updaterequirementsorpyproject. - Find-and-replace the imports as shown above.
- Run your test suite - it should pass unchanged.