v0.2.0: Cross-Examination ⚖️
⚖️ Hands you the tools to put your data on the stand where it matters most: in your tests.
Meet pytest-probatio, a companion package that lets a Probatio schema stand in as a pytest assertion matcher. The schema reads as the expected shape, and a mismatch is explained by Probatio's path-precise errors instead of a bare assert.
from pytest_probatio import Exact, Partial
from probatio import Port
def test_response(response):
# Exact: an extra key makes it unequal.
assert response == Exact({"name": str, "port": Port()})
# Partial: extra keys are allowed.
assert response == Partial({"name": str})When the data does not match, the failure points at the exact offending value, even deep inside a nested or composed shape:
data does not match the probatio schema (==):
data['users'][0]['email']: expected an email address
It is plain pytest output, so a failing schema match flows straight into pytest-github-actions-annotate-failures and becomes a GitHub annotation on the test, with no extra setup. Define a schema once and reuse it across as many tests as you like. It ships as a separate distribution, so the core library stays dependency-free, and it is released lock-step with Probatio at the same version.
pip install pytest-probatioThis release also tightens the evidence. The atheris fuzzers that guard the untrusted-input surfaces now run on every pull request on Python 3.13, not just locally. That is not decoration: turning them loose in CI found and closed a handful of raw-exception leaks (in the OpenAPI and JSON Schema codecs, the IP validators, and Contains). The safe-validator contract, a built-in validator only ever raises Invalid, never a raw exception, is now enforced continuously rather than checked by hand.
📚 Docs: https://probatio.frenck.dev
Put your data to the proof. ⚖️
../Frenck
Blogging my personal ramblings at frenck.dev