Trust the Shape: Schema Validation & Negative Testing
Checking one field at a time is like proofreading a form by reading only the name box. Whole classes of bugs slip past. There's a faster, safer way.
The idea, in one line
Instead of poking at fields one by one, describe the shape the whole response should have, then check the reply against it in a single line. Pydantic v2 does this for you.
How to spot when you need it
- A key got renamed and your test never noticed
- A number arrived as a string (
"123"instead of123) - A field came back null where you expected text
- You're writing five asserts to check one response body
See it work
You define a BaseModel with typed fields. Required fields have no default; optional ones use Optional[str] = None. Feed the response to Model.model_validate(data) (or model_validate_json for raw JSON). If every field fits, you get a clean typed object back. If anything is off, Pydantic raises a ValidationError that lists all the problems at once.
import requests
from pydantic import BaseModel
from typing import Optional
class Post(BaseModel):
id: int
userId: int
title: str
body: Optional[str] = None # optional field
BASE = "https://jsonplaceholder.typicode.com"
def test_response_matches_schema():
r = requests.get(f"{BASE}/posts/1", timeout=5)
post = Post.model_validate(r.json()) # raises if shape is wrong
assert post.id == 1Read it top to bottom: you declared what a Post should look like, then handed the response to the model. One line replaced a fistful of field checks.
Advanced — negative testing and strict mode
Pydantic is helpful and will coerce sensibly — the string "123" becomes the int 123. When a type must be exact, turn on strict mode so it won't quietly convert. Schema checks also pair naturally with negative testing: the paths where things should fail on purpose.
- Send a bad payload, expect 400
- Drop the auth header, expect 401
- Ask for a missing id, expect 404
Grounded in the official Pydantic v2 docs (Models & validation)
All lessons in API Automation from Zero to Confident
- The HTTP Mental Model & Your First Postman Collection
- Recreate It in Code: requests + pytest with Shared State
- Trust the Shape: Schema Validation & Negative Testing
- Getting Past the Gate: API Keys, Bearer/JWT & OAuth2
- SQL for Testers: Prove the API Actually Wrote to the DB
- Mocking & Contracts: Fast, Offline, Reliable Tests