postman-collections
Authors Postman collections (requests + tests + variables + environments), runs them headless via the Newman CLI, configures reporters (cli / json / junit / html) for CI artifact upload, and uses iteration data files (JSON / CSV) for data-driven runs. Use when the project ships HTTP API tests authored in Postman and the team needs CI execution alongside or instead of the Postman desktop runner.
postman-collections
Overview
Postman is a popular GUI for HTTP API authoring; Newman is its official CLI for running the same collections headlessly in CI (newman-readme). The integration shape is two-step:
This skill covers the headless Newman side. Authoring inside Postman itself is a GUI workflow; the canonical reference is learning.postman.com and is out of scope for an automated agent.
When to use
If the team uses TypeScript / JavaScript and prefers code-first authoring, evaluate tavern-testing (YAML) or karate-testing (Karate DSL) before adopting Postman/Newman - those keep tests next to source code rather than in a separate JSON artifact.
Install
npm install -g newman(Per newman-readme.)
For per-project install (preferred for CI determinism):
npm install --save-dev newmanFor the HTML reporter (external, separate install):
npm install --save-dev newman-reporter-htmlextraRunning
The canonical invocation (newman-readme):
newman run <collection-file-source> [options]<collection-file-source> can be:
Key flags
Per newman-readme:
| Flag | Purpose |
|---|---|
-e, --environment <source> | Postman environment file (path or URL). |
-d, --iteration-data <source> | Data file for iterations: JSON or CSV. |
-r, --reporters <name> | Comma-separated list: cli,json,junit,html (htmlextra). |
--bail [folder|failure] | Stop on first error; modifier scopes the bail trigger. |
--reporter-junit-export <path> | Where to write the JUnit XML (when junit reporter). |
--reporter-json-export <path> | Where to write the JSON summary. |
--timeout-request <ms> | Per-request timeout. |
--insecure | Disable TLS verification (use only against test servers). |
--delay-request <ms> | Delay between requests; helps when the server has rate limits. |
Worked example
newman run examples/sample-collection.json \
-e environment.json \
-d data.csv \
-r cli,json,junit \
--timeout-request 5000 \
--reporter-junit-export results.xml \
--reporter-json-export results.json \
--bail folder(Adapted from newman-readme.)
Reporters
The four built-in / canonical reporters per newman-readme:
| Reporter | Purpose |
|---|---|
cli | Terminal output; enabled by default. |
json | Full JSON summary of every request and assertion result. |
junit | JUnit XML - consumable by GitHub Actions, GitLab, Jenkins. |
html | Static HTML report; requires newman-reporter-htmlextra. |
JUnit is the canonical CI choice - every major CI platform ingests JUnit XML, surfaces test counts on the run summary, and lets the team click through to per-assertion failures.
For richer per-test details (which assertion in which folder failed with which response), pair junit with json and upload both as build artifacts.
Authoring tests inside the collection
Tests in Postman live in the Tests tab of each request and run after the response is received. The runtime is a sandboxed JavaScript environment with pm.* globals:
pm.test('status is 200', () => {
pm.response.to.have.status(200);
});
pm.test('body is JSON with .order_id', () => {
const json = pm.response.json();
pm.expect(json).to.have.property('order_id').that.is.a('number');
});
pm.test('saves order_id for next request', () => {
pm.collectionVariables.set('order_id', pm.response.json().order_id);
});Each pm.test('...', () => {}) call becomes one entry in the JUnit XML / JSON output - name them clearly so the CI run summary is readable.
CI integration
# .github/workflows/api-tests.yml
name: api-tests
on:
pull_request:
push:
branches: [main]
jobs:
newman:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Newman run
env:
API_BASE_URL: ${{ secrets.STAGING_BASE_URL }}
API_TOKEN: ${{ secrets.API_TOKEN }}
run: |
npx newman run collections/orders.postman_collection.json \
-e environments/staging.postman_environment.json \
-r cli,json,junit \
--reporter-junit-export results.xml \
--reporter-json-export results.json \
--bail failure \
--timeout-request 10000
- name: Upload reports
if: always()
uses: actions/upload-artifact@v4
with:
name: newman-reports
path: |
results.xml
results.json
retention-days: 14
- name: Surface JUnit results in summary
if: always()
uses: dorny/test-reporter@v1
with:
name: API tests
path: results.xml
reporter: java-junitif: always() on both upload + reporter steps is critical - when a collection fails, the reports are exactly when you need them.
Anti-patterns
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Hard-coded environment URLs in the collection JSON | Collection breaks across staging / prod / local. | Move to *.postman_environment.json files; pass via -e. |
| Storing API tokens in the collection JSON | Tokens leak into git. | Use environment files committed without secrets, or pull tokens from CI env vars referenced as {{API_TOKEN}}. |
| Running collections in PR CI against production | Tests pollute prod data; rate limits trip; observability noise. | Always run against a staging or ephemeral env. |
Sequential pm.test blocks that share state | One failure cascades into N false positives. | Each request's tests should be independent - use pm.collectionVariables to share derived data, not assertion state. |
| One giant collection with 200 requests | Newman runs serially; CI time grows linearly. | Split into per-domain collections; parallelize at the CI matrix level. |
Missing --bail in CI | Newman runs all requests even after a failure; noisy logs. | Use --bail failure for fast feedback; --bail folder to scope the bail to a logical group. |