Postman Test Scripts and Assertions — Validating API Responses Automatically
In this tutorial, you will learn about Postman Test Scripts and Assertions. We cover key concepts, practical examples, and best practices to help you master this topic.
Postman test scripts use the Chai assertion library to validate API responses — status codes, response body structure, headers, response times, and data values — with descriptive test names for clear reporting.
Code Example: Comprehensive Response Validation
// Tests tab — collection-level test script
const jsonData = pm.response.json();
const responseTime = pm.response.responseTime;
// === STATUS CODE VALIDATION ===
pm.test("Status code is 2xx", function () {
pm.response.to.have.status(201);
});
// === RESPONSE BODY STRUCTURE ===
pm.test("Response has required fields", function () {
pm.expect(jsonData).to.be.an("object");
pm.expect(jsonData).to.include.keys(["id", "name", "severity", "created_at"]);
pm.expect(jsonData).to.not.have.property("internal_notes");
});
// === DATA TYPE VALIDATION ===
pm.test("Fields have correct data types", function () {
pm.expect(jsonData.id).to.be.a("string");
pm.expect(jsonData.name).to.be.a("string");
pm.expect(jsonData.severity).to.be.oneOf(["low", "medium", "high", "critical"]);
pm.expect(jsonData.created_at).to.match(
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/
);
});
// === RESPONSE TIME ===
pm.test("Response time is acceptable", function () {
pm.expect(responseTime).to.be.below(800);
// Warn if above 500ms
if (responseTime > 500) {
console.warn(`Slow response: ${responseTime}ms`);
}
});
// === HEADER VALIDATION ===
pm.test("Response has secure headers", function () {
pm.response.to.have.header("X-Content-Type-Options");
pm.response.to.have.header("X-Frame-Options");
pm.expect(pm.response.headers.get("X-Content-Type-Options"))
.to.eql("nosniff");
});
// === ERROR RESPONSE VALIDATION ===
if (pm.response.code === 422) {
pm.test("Validation error has proper structure", function () {
pm.expect(jsonData).to.have.property("error");
pm.expect(jsonData).to.have.property("details");
pm.expect(jsonData.details).to.be.an("array");
});
}
Code Example: JSON Schema Validation
// Schema validation with tv4 (built-in Postman library)
const tv4 = require("tv4");
const threatSchema = {
type: "object",
required: ["id", "name", "severity", "created_at", "source_ip"],
properties: {
id: { type: "string", pattern: "^[a-f0-9]{24}$" },
name: { type: "string", minLength: 3, maxLength: 200 },
severity: { type: "string", enum: ["low", "medium", "high", "critical"] },
source_ip: { type: "string", pattern: "^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$" },
created_at: { type: "string", format: "date-time" },
description: { type: "string" },
tags: {
type: "array",
items: { type: "string" }
}
}
};
pm.test("Response matches threat schema", function () {
const valid = tv4.validate(pm.response.json(), threatSchema);
if (!valid) {
console.log("Validation errors:", JSON.stringify(tv4.error, null, 2));
}
pm.expect(valid).to.be.true;
});
// Array response schema validation
const threatListSchema = {
type: "object",
required: ["threats", "total", "page"],
properties: {
threats: {
type: "array",
items: { $ref: "#/definitions/threat" }
},
total: { type: "integer", minimum: 0 },
page: { type: "integer", minimum: 1 },
page_size: { type: "integer" }
},
definitions: {
threat: {
type: "object",
required: ["id", "name", "severity"]
}
}
};
Code Example: Conditional and Data-Driven Tests
// Conditional tests based on response data
pm.test("High severity threats require immediate action", function () {
const jsonData = pm.response.json();
if (jsonData.severity === "high" || jsonData.severity === "critical") {
pm.expect(jsonData).to.have.property("priority");
pm.expect(jsonData.priority).to.be.above(0);
pm.expect(jsonData).to.have.property("assigned_to");
}
});
// Pagination validation
pm.test("Pagination metadata is correct", function () {
const jsonData = pm.response.json();
pm.expect(jsonData).to.have.property("page");
pm.expect(jsonData).to.have.property("total_pages");
// If not on the last page, next page URL should exist
if (jsonData.page < jsonData.total_pages) {
pm.expect(jsonData).to.have.property("next_page");
pm.expect(jsonData.next_page).to.be.a("string");
}
// If on the last page, no next page
if (jsonData.page === jsonData.total_pages) {
pm.expect(jsonData.next_page).to.be.undefined;
}
});
// Array item validation
pm.test("All threats in list have valid data", function () {
const threats = pm.response.json().threats;
pm.expect(threats.length).to.be.at.least(1);
threats.forEach(function(threat, index) {
pm.expect(threat).to.have.property("id");
pm.expect(threat).to.have.property("name");
pm.expect(threat.name.length).to.be.at.least(3);
});
});
Common Mistakes
1. Testing Only Status Codes
Status codes indicate the HTTP protocol result, not the correctness of the response. Always validate the response body content and structure.
2. Assertions Without Descriptive Names
Test names appear in reports and CI output. Use descriptive names: "Response includes pagination metadata" instead of "Test 1".
3. Not Handling Array Responses
API endpoints return arrays. Your tests must handle both single objects and arrays with validation for each element.
4. Hardcoded Expected Values
Expected values should come from the request data, not be hardcoded. For a create endpoint, verify the response name matches the sent name.
5. Missing Negative Tests
Test that errors return the correct status codes and error structures. Validate that invalid input produces appropriate error responses.
Practice Questions
- What Chai assertion styles does Postman support?
- How do you validate a response against a JSON schema?
- What is the difference between pm.test and pm.expect?
- How do you test array responses in Postman?
- Why should test assertions have descriptive names?
Answers:
- Postman supports BDD (expect/should) and Assert (assert) styles. BDD style (pm.expect) is recommended for readability.
- Use the tv4 library (pre-installed): tv4.validate(response, schema). Check the result and log errors on failure.
- pm.test defines a named test case. pm.expect makes an assertion within a test. Multiple pm.expect calls can exist within one pm.test.
- Loop through the array with forEach. Validate each element's structure and required fields. Check the array length is within expected bounds.
- Test names appear in reports, CI logs, and team dashboards. Clear names help identify which test failed without inspecting the code.
Challenge: Build a comprehensive Postman test script suite for a threat intelligence API with schema validation, data-Type Checking, conditional assertions for error states, pagination validation, and automated data cleanup verification.
FAQ
Mini Project
Build a Postman test script suite for a threat intelligence API with: JSON schema validation for all endpoints, response time thresholds, conditional severity checks, pagination metadata validation, error response structure validation, and automated data cleanup assertions.
What's Next
Now learn about Data-Driven Testing in Postman for running the same tests with multiple data sets.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro