Skip to course content
Free FastAPI backend course

FastAPI for AI Backend Development

Unit 09.03: Asserting on the contract, not the wording

Assert the contract from Module 1, not the exact response you happened to get.

Allowed values, ranges, required fields, no extras

A response checked against five contract properties instead of an exact match.

The code compares both approaches.

RESPONSE = {"category": "billing", "confidence": 0.87,
            "request_id": "r-8841"}

brittle = RESPONSE == {"category": "billing", "confidence": 0.9,
                       "request_id": "r-8841"}
contract = [
    ("status is 200", True),
    ("category is one of the four", RESPONSE["category"] in
     {"billing", "technical", "account", "other"}),
    ("confidence is a float in range", 0 <= RESPONSE["confidence"] <= 1),
    ("request_id is present", "request_id" in RESPONSE),
    ("no unexpected fields", set(RESPONSE) <= {"category", "confidence",
                                               "request_id"}),
]
print(f"exact-match assertion: {brittle}   <- fails on any confidence change")
for name, ok in contract:
    print(f"  {'PASS' if ok else 'FAIL'} {name}")

# Assert the contract from Module 1: allowed values, ranges, required fields,
# and no extras. The last check is the one that catches an accidental leak of
# an internal field.

The exact match fails on a confidence of 0.87 against 0.9 - a difference nobody cares about. The five contract checks all pass and each names something a caller relies on.

The last check is the one worth copying: asserting no *unexpected* fields catches an internal field accidentally leaking into a response, which is the failure the response model exists to prevent.

The mistake this prevents

The mistake is asserting on the full response dictionary. It breaks every time anyone adds a field, including deliberately, so the test becomes noise and eventually gets loosened to nothing.

Takeaway

Assert allowed values, ranges, required fields and the absence of unexpected ones. Exact-response assertions fail on harmless changes.