Skip to content

feat: add expect() and AssertableValue for generic fluent assertions#32

Merged
othercodes merged 1 commit into
masterfrom
feat/expectations
May 15, 2026
Merged

feat: add expect() and AssertableValue for generic fluent assertions#32
othercodes merged 1 commit into
masterfrom
feat/expectations

Conversation

@othercodes
Copy link
Copy Markdown
Owner

Summary

Adds a generic fluent assertion layer (expect() / AssertableValue) so the same fluent vocabulary that powers AssertableJson, AssertableHtml, AssertableMCP, etc. extends to any value under test — domain objects, primitives, collections.

This is the foundational layer of pyssertive's mission: one fluent vocabulary for everything you test, from a single value to full HTTP responses.

from pyssertive import expect

expect(user.email).matches(r".+@.+").starts_with("alice")
expect([1, 2, 3]).has_count(3).contains(2)
expect(orders).each().has_attribute("status", "paid")

What's new

  • expect(value) factory + AssertableValue class with ~30 matchers across:
    • Equality / identity (equals, does_not_equal, is_same_as, is_none, ...)
    • Truthiness (is_truthy, is_true, is_false, ...)
    • Types (is_instance_of, is_not_instance_of, is_type)
    • Comparisons (is_greater_than, is_at_least, is_between, ...)
    • Collections (has_count, contains, is_empty, ...)
    • Dict/object (has_key, has_attribute, ...)
    • Strings (matches, starts_with, ends_with, ...)
    • Higher-order (each(), sequence())
  • Custom expectations via subclass — fully typed, IDE-autocompleted, mypy-checked.
  • Top-level export: from pyssertive import expect, AssertableValue.

README improvements (also in this PR)

  • New ### Expectations section at the top of ## Usage, framing expect() as the foundational fluent vocabulary.
  • Tagline + first Features bullet updated to reflect "one vocabulary for everything you test".
  • New top-level Table of Contents (752-line README needed it).
  • MCP section refactored:
    • Big intro block split into 4 focused sub-sections (#### Initialize handshake / #### Tool call — success / #### Tool-level error / #### Protocol error).
    • New #### Method catalog with one sub-table per Assertable (AssertableMCP, AssertableToolList, AssertableToolDef, AssertableToolCall, AssertableContent).
    • MessageBuilder examples trimmed to 3 prototypical patterns + new flat method catalog table covering all 14 methods (including previously undocumented listing_resources / listing_prompts).
    • Orphan paragraph promoted to #### Catalog-wide invariants.
  • ### HTTP — Basic Example merged into ### HTTP Status Assertions (no orphan section).
  • > Requires the Django adapter note added to ### Database Assertions.
  • Stale > Breaking change: assert_json() paragraph removed.

Test plan

  • 99 new tests for AssertableValue covering happy + sad paths for every matcher.
  • Parametrized tests for is_instance_of / is_not_instance_of covering single types and tuples.
  • mypy strict clean (39 source files).
  • Coverage 100% maintained.
  • ruff lint + format clean.
  • All 969 tests pass.

@othercodes othercodes force-pushed the feat/expectations branch from 7e92cc0 to e7f5e3b Compare May 14, 2026 23:53
@sonarqubecloud
Copy link
Copy Markdown

@othercodes othercodes merged commit 8fe0675 into master May 15, 2026
33 checks passed
@othercodes othercodes deleted the feat/expectations branch May 15, 2026 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant