Skip to content

Postman Test Scripts and Assertions — Validating API Responses Automatically

DodaTech Updated 2026-06-28 5 min read

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

  1. What Chai assertion styles does Postman support?
  2. How do you validate a response against a JSON schema?
  3. What is the difference between pm.test and pm.expect?
  4. How do you test array responses in Postman?
  5. Why should test assertions have descriptive names?

Answers:

  1. Postman supports BDD (expect/should) and Assert (assert) styles. BDD style (pm.expect) is recommended for readability.
  2. Use the tv4 library (pre-installed): tv4.validate(response, schema). Check the result and log errors on failure.
  3. 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.
  4. Loop through the array with forEach. Validate each element's structure and required fields. Check the array length is within expected bounds.
  5. 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

Can I use async/await in Postman tests?

No. Postman sandbox does not support async/await. Use callbacks with pm.sendRequest for asynchronous operations in tests.

How do I reuse test scripts across requests?

Write tests at the collection level (applied to all requests) and folder level (applied to all requests in a folder). Override with request-level tests.

Can I stop the collection run if a test fails?

Yes. Use pm.expect(...) with pm.response.to.have.status(201) — if the assertion fails, the test fails but the collection continues. Use Postman's 'Stop if failed' option in the collection runner.

How do I test file downloads?

Check the Content-Type header (application/octet-stream, application/pdf). Verify the Content-Disposition header contains the filename. Check the response size is reasonable.

Can I use external data in tests?

Yes. Use data files (CSV/JSON) with the collection runner. Access data file values via pm.iterationData.get('fieldname').

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