Skip to main content

Fluent assertion library for Python with composable matchers, structural matching, and full type safety

Project description

assertpy2

Fluent assertion library for Python with composable matchers, structural matching, and full type safety.
A modern, batteries-included fork of assertpy.

CI PyPI version Downloads Python Coverage
Documentation Ruff uv ty OpenSSF Scorecard OpenSSF Best Practices


Quick start

pip install assertpy2  # drop-in replacement for assertpy, just change the import
from assertpy2 import assert_that

def test_user():
    user = {"name": "Alice", "age": 30, "roles": ["viewer", "editor"]}

    assert_that(user).contains_key("name", "age")
    assert_that(user["age"]).is_between(18, 120)
    assert_that(user["roles"]).contains("viewer").does_not_contain("admin")
    assert_that(user).has_name("Alice")

Why fluent assertions?

# bare assert - passes, but failure message is useless
assert user["age"] >= 18
# AssertionError

# assertpy2 - same check, clear failure message
assert_that(user["age"]).is_greater_than_or_equal_to(18)
# AssertionError: Expected <16> to be greater than or equal to <18>, but was not.

# bare assert - three separate statements
assert isinstance(items, list)
assert len(items) == 3
assert "admin" in items

# assertpy2 - one fluent chain
assert_that(items).is_type_of(list).is_length(3).contains("admin")

Type-aware autocomplete

assert_that() uses @overload to return type-specific Protocols. Your IDE shows only methods relevant to the value you're testing, not all 100+:

  • assert_that("hello"). → string methods: starts_with, matches, is_alpha, ...
  • assert_that(42). → numeric methods: is_positive, is_between, is_close_to, ...
  • assert_that(Path("/tmp")). → path methods: exists, is_file, is_readable, ...
  • assert_that(my_dict). → dict methods: contains_key, contains_entry, has_json_path, ...
  • assert_that(b"\x89PNG"). → bytes methods: starts_with_bytes, is_valid_utf8, decoded_as, ...

9 type-specific Protocols instead of one Any. Works in PyCharm, VS Code, and any LSP-compatible editor.


Features

Fluent API

  • Composable matchers: match.greater_than(5), match.is_uuid(), combine with &, |, ~. Also work with plain assert ==.
  • Structural matching: matches_structure() for declarative dict/API response validation.
  • Universal negation: .not_ inverts any assertion without dedicated is_not_* methods.
  • Collection pipeline: filtered_on(), mapped(), flat_mapped(), first(), last(), element(), single().
  • Fluent chaining: write assertions as readable one-liners that chain naturally.

Built-in types

Testing

  • Soft assertions: thread-safe, async-safe via contextvars. Group errors with sa.group(), or use assert_all().
  • Async assertions: eventually() with polling/retry for eventual consistency.
  • Structured errors: AssertionFailure with .actual, .expected, .diff attributes.
  • Rich pytest diffs: recursive structural diffs for lists, sets, strings, dicts, dataclasses, namedtuples, Pydantic models. Circular reference protection.
  • Snapshot testing: store and compare data structures in JSON format.

Type safety

Extensibility

  • Custom matchers: register_matcher() for domain-specific matchers, composable with &, |, ~.
  • Regex group extraction: extracting_group() and matches_with_groups() for regex captures.
  • Extensions: add_extension() for custom assertion methods.

Integrations

  • Allure: auto-attach structured diff and actual/expected data to reports. pip install assertpy2[allure].
  • Behave: ready-made parameter types for step definitions. pip install assertpy2[behave].

See the full documentation for all assertion methods, examples, and advanced features.


Integrations

Allure

When allure-pytest is installed, the pytest plugin auto-attaches structured failure data to Allure reports as JSON attachments.

pip install assertpy2[allure]

Three modes controlled via pytest.ini (or pyproject.toml):

Mode What is attached
diff (default) Structured Diff JSON (path-level breakdown)
full Structured Diff + actual/expected JSON
off Nothing
# pyproject.toml
[tool.pytest.ini_options]
assertpy2_allure = "full"

Behave

Ready-made parameter types for Behave step definitions:

pip install assertpy2[behave]
# in environment.py or steps/conftest.py
from assertpy2.behave_matchers import register_assertpy_types
register_assertpy_types()

Then use in step definitions:

@given('a user aged {age:PositiveInt}')
def step_impl(context, age):
    context.age = age  # already validated as int > 0

Available types: PositiveInt, NonNegativeInt, PositiveFloat, NonEmptyString, BoolLike.


BSD 3-Clause License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

assertpy2-2.7.0.tar.gz (214.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

assertpy2-2.7.0-py3-none-any.whl (65.1 kB view details)

Uploaded Python 3

File details

Details for the file assertpy2-2.7.0.tar.gz.

File metadata

  • Download URL: assertpy2-2.7.0.tar.gz
  • Upload date:
  • Size: 214.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for assertpy2-2.7.0.tar.gz
Algorithm Hash digest
SHA256 a271440a43a5c48457f90a997b91febcd7a0b41a4f437e3173fa4eb020d336e8
MD5 2e11bb0a378ee7943a49b9e7afcffadc
BLAKE2b-256 b36466039a19bd37295d4970776dc87688f0e8ba1ba29989507c5b9dc004c8a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for assertpy2-2.7.0.tar.gz:

Publisher: publish.yml on Solganis/assertpy2

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file assertpy2-2.7.0-py3-none-any.whl.

File metadata

  • Download URL: assertpy2-2.7.0-py3-none-any.whl
  • Upload date:
  • Size: 65.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for assertpy2-2.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 80d7b152390c40e0ae2a8f25200c458b4d15a0f02fe23a2d5e5c354a76090ff5
MD5 919119ef7810d39963035cb3990e933a
BLAKE2b-256 4e32784d0abb371c7c52a70bcc110dd1c5287500c8bc2702203821701a7cf70d

See more details on using hashes here.

Provenance

The following attestation bundles were made for assertpy2-2.7.0-py3-none-any.whl:

Publisher: publish.yml on Solganis/assertpy2

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page