Postman API Testing
Write automated API tests in Postman: test scripts, assertions, chaining requests, data-driven runs, and running collections in CI with Newman.
Postman is more than a request sender. Every request can carry JavaScript that runs before it is sent and after the response arrives, which turns a collection into an automated test suite. This guide focuses on writing assertions, chaining requests, running collections repeatedly, and executing them in CI with Newman, the Postman command-line runner. For first-time setup, workspaces, and environments, see the companion Postman tool guide.
When to use it
Use Postman for API functional and contract tests, smoke tests after deployments, and regression suites that non-developers can read. For very high load, use a dedicated tool such as k6.
Writing test scripts
Open a request and use the Scripts tab (Tests, in older versions). Scripts use the pm object and a Chai-style assertion syntax.
pm.test("status is 200", function () {
pm.response.to.have.status(200);
});
pm.test("responds within 500 ms", function () {
pm.expect(pm.response.responseTime).to.be.below(500);
});
pm.test("returns JSON with expected shape", function () {
const body = pm.response.json();
pm.expect(body).to.have.property("id");
pm.expect(body.email).to.be.a("string");
pm.expect(body.roles).to.be.an("array").that.is.not.empty;
});
pm.test("content type is JSON", function () {
pm.response.to.have.header("Content-Type", /application\/json/);
});
Chaining requests with variables
Save values from one response and use them in the next. Log in first, store the token, then reference it.
// Tests tab of POST /auth/login
const token = pm.response.json().accessToken;
pm.environment.set("token", token);
In later requests, set the Authorization header to the word Bearer followed by the token variable in double curly braces. Use a pre-request script when you need to generate data on the fly:
pm.variables.set("orderRef", "ORD-" + Date.now());
pm.variables.set("email", pm.variables.replaceIn("{{$randomEmail}}"));
Control the order within a run using pm.execution.setNextRequest("Request name") or by arranging requests in folders. Keep chains short and make independent tests independent so one failure does not cascade.
Schema validation
Catch contract drift by validating the whole response against a JSON schema.
const schema = {
type: "object",
required: ["id", "email"],
properties: {
id: { type: "integer" },
email: { type: "string" }
}
};
pm.test("matches schema", function () {
pm.response.to.have.jsonSchema(schema);
});
Data-driven runs
The Collection Runner can iterate a CSV or JSON file, running the collection once per row. Reference columns by name in double curly braces in requests, or read them in scripts with pm.iterationData.get("column"). This is ideal for boundary values and permission matrices.
Running in CI with Newman
npm install -g newman newman-reporter-htmlextra
newman run collection.json \
-e staging.environment.json \
-d testdata.csv \
--env-var "token=$API_TOKEN" \
--reporters cli,junit,htmlextra \
--reporter-junit-export results.xml \
--bail
Export the collection and environment from Postman, or sync them through the Postman API. Newman returns a non-zero exit code when any assertion fails, so your pipeline stops. A GitHub Actions step is just npx newman run collection.json -e staging.environment.json after installing Node. Publish the JUnit file so failures show in the CI UI.
Common pitfalls
- Secrets in exported files. Pass tokens through CI secrets and
--env-var, not committed environment JSON. - Assertions that always pass, such as tests with no
pm.expect. A test with no failing branch proves nothing. - Order-dependent tests that break when run alone or in parallel.
- Testing only the happy path. Add 400, 401, 403, 404, and 409 cases.
- Brittle exact-match assertions on timestamps or generated IDs. Assert on type and shape.
- Hardcoded hosts instead of an environment variable.
Where it fits in an architecture
API tests sit between unit tests and end-to-end UI tests. They verify the contract between services quickly and without a browser. Run a smoke collection after every deployment and the full suite nightly. Share the OpenAPI definition as the source of truth and generate or validate collections against it so documentation, tests, and implementation stay aligned.
Key takeaways
- Treat collections as executable test suites using pm.test and pm.expect.
- Chain requests through variables, but keep tests independent where possible.
- Validate schemas to catch contract drift.
- Run collections headlessly with Newman and fail the build on errors.
- Keep secrets out of version control.