Module 3 · Python for SDETs
API Testing
with requests
Drive every HTTP verb against a real API — and read what comes back
GET / POST
PUT / DELETE
status & JSON
CRUD lifecycle
Anatomy of a response
r = requests.get("…/api/products/1")
r.status_code # 200
r.ok # True for any 2xx/3xx
r.headers # case-insensitive dict
r.json() # body → dict / list
🔢
.status_code
the integer status (200, 201, 404…)
✅
.ok
True for any status below 400
📋
.headers
response headers, case-insensitive
📦
.json()
parse the body into Python
Each verb, its success status
The four HTTP verbs
POST
201
made it; body has the new record
📌requests never raises on a 4xx — the status is just data you assert. Reads use plain requests; writes reseed with the reset_db fixture so re-runs stay clean.
json= sends a body, the server does work
payload = {
"email": "customer@test.io",
"items": [{"product_id": 1, "quantity": 2}],
}
r = api.post("…/api/orders", json=payload)
201Created
total: 59.98 # 29.99 × 2, server-side
json= also sets Content-Type for you. The total is computed — assert it with pytest.approx.
The shape of a real API test
A full lifecycle, one test
🔁Every verb in one coherent test — and it cleans up after itself. Prove the effect (the follow-up GET → 404), not just the delete status.
🌐
The whole
API surface
Read and write, assert status + body, and run a full CRUD lifecycle
🧪
Practice
CRUD against TestMarket Lab — capture the new id from the POST response
♻️
reset_db
Writes reseed first, so your tests stay independent and re-runnable
➡️
Module 4
Negative & validation — 400 / 401 / 404 / 409, failing the right way