Writing Assertions
Sending a request and eyeballing the response worked fine for one request, but it doesn't scale
and it isn't repeatable — you can't hand "look at the JSON and see if it seems right" to a CI
pipeline. Postman lets you attach real, automated checks to any request using the
Tests tab (in newer Postman versions this lives under Scripts → Post-response,
but it's the exact same JavaScript engine). This lesson writes a complete set of assertions for the
Get Recipe By ID request against the RecipeBox API.
Where Assertions Live
Open the Get Recipe By ID request (GET {{baseUrl}}/recipes/42) and click the Tests tab (or Scripts → Post-response). Code you write here runs automatically after the response comes back, before you see the result in the Test Results panel.
The pm.test() Structure
Every assertion follows the same shape: a name string describing what's being checked, and a callback that throws if the check fails.
// General shape
pm.test("description of what this checks", function () {
pm.expect(/* actual value */).to.eql(/* expected value */);
});
pm.test reports pass/fail per assertion in the Test Results tab (with a count like "3/4
passed"), and Postman turns any failed assertion into a red mark that's impossible to miss — which
is the entire point versus manually scanning JSON.
Checking the Status Code
The single most common assertion: did the request even succeed?
pm.test("status code is 200", function () {
pm.response.to.have.status(200);
});
If the RecipeBox API returned 404 instead — say, recipe 42 was deleted — this assertion fails immediately and clearly names the problem, instead of you discovering it three assertions later when a field access throws a confusing error.
Checking Response Fields
Parse the body once with pm.response.json(), then assert against individual fields:
var jsonData = pm.response.json();
pm.test("id matches the requested recipe", function () {
pm.expect(jsonData.id).to.eql(42);
});
pm.test("title is present and is a string", function () {
pm.expect(jsonData).to.have.property("title");
pm.expect(jsonData.title).to.be.a("string");
});
to.have.property() checks a field exists at all — useful for catching a backend regression where a field silently disappears from the response. to.be.a() checks its type, which catches the sneakier bug where prepMinutes comes back as the string "20" instead of the number 20.
Checking Response Time
Postman exposes timing on every response, so performance regressions can be asserted just like data:
pm.test("response time is under 500ms", function () {
pm.expect(pm.response.responseTime).to.be.below(500);
});
Full Worked Example: Get Recipe By ID
Putting it together, here's a complete Tests script for GET {{baseUrl}}/recipes/42 with four assertions:
pm.test("status code is 200", function () {
pm.response.to.have.status(200);
});
var jsonData = pm.response.json();
pm.test("id matches the requested recipe", function () {
pm.expect(jsonData.id).to.eql(42);
});
pm.test("prepMinutes is a positive number", function () {
pm.expect(jsonData.prepMinutes).to.be.a("number");
pm.expect(jsonData.prepMinutes).to.be.above(0);
});
pm.test("response time is under 500ms", function () {
pm.expect(pm.response.responseTime).to.be.below(500);
});
Click Send and check the Test Results tab — Postman lists all four assertions with a pass/fail count. This is exactly the pattern in the "Quick Look Ahead" example back on the track's home page, now written out in full.
jsonData.title.toLowerCase() when title is actually undefined) fails the whole script, not just one pm.test block. Keep each assertion's logic inside its own callback so one bad field doesn't hide the results of every other check.id — from one request into the next, so you can test realistic multi-step flows.