API Testing Development (Postman/Newman)
Postman is a GUI tool for working with APIs with the ability to write JavaScript tests. Newman is a CLI runner for Postman collections for CI/CD integration. Convenient for REST API testing: checking statuses, response schemas, business logic.
Collection Structure
Collection: E-commerce API
├── Auth
│ ├── POST /auth/login
│ ├── POST /auth/refresh
│ └── POST /auth/logout
├── Products
│ ├── GET /products (list)
│ ├── GET /products/:id
│ ├── POST /products (create)
│ └── PATCH /products/:id
└── Orders
├── POST /orders (create)
└── GET /orders/:id
Variables and Environments
// environments/staging.json
{
"name": "Staging",
"values": [
{ "key": "BASE_URL", "value": "https://api-staging.example.com" },
{ "key": "API_KEY", "value": "{{$STAGING_API_KEY}}" },
{ "key": "auth_token", "value": "" }
]
}
Tests in Postman
// POST /auth/login — Tests tab
pm.test('Status code is 200', () => {
pm.response.to.have.status(200);
});
pm.test('Response has token', () => {
const json = pm.response.json();
pm.expect(json).to.have.property('access_token');
pm.expect(json.access_token).to.be.a('string').and.not.empty;
});
pm.test('Response time is acceptable', () => {
pm.expect(pm.response.responseTime).to.be.below(500);
});
// Save token for next requests
const json = pm.response.json();
pm.environment.set('auth_token', json.access_token);
pm.environment.set('user_id', json.user.id);
// GET /products — schema validation
pm.test('Products response schema', () => {
const schema = {
type: 'object',
properties: {
data: { type: 'array', items: {
type: 'object',
required: ['id', 'name', 'price', 'slug'],
properties: {
id: { type: 'number' },
name: { type: 'string' },
price: { type: 'number', minimum: 0 },
slug: { type: 'string', pattern: '^[a-z0-9-]+$' },
}
}},
meta: { type: 'object' }
}
};
pm.response.to.have.jsonSchema(schema);
});
pm.test('Products are sorted by created_at DESC', () => {
const products = pm.response.json().data;
for (let i = 0; i < products.length - 1; i++) {
pm.expect(new Date(products[i].created_at))
.to.be.at.least(new Date(products[i+1].created_at));
}
});
Pre-request Scripts
// Auto-refresh token before request
const token = pm.environment.get('auth_token');
const expiresAt = pm.environment.get('token_expires_at');
if (!token || Date.now() > expiresAt) {
pm.sendRequest({
url: pm.environment.get('BASE_URL') + '/auth/refresh',
method: 'POST',
header: { 'Content-Type': 'application/json' },
body: { mode: 'raw', raw: JSON.stringify({
refresh_token: pm.environment.get('refresh_token')
})}
}, (err, res) => {
const json = res.json();
pm.environment.set('auth_token', json.access_token);
pm.environment.set('token_expires_at', Date.now() + (json.expires_in * 1000));
});
}
Newman — Running in CI
npm install -g newman newman-reporter-htmlextra
# Basic run
newman run collection.json \
--environment environments/staging.json \
--reporters cli,htmlextra \
--reporter-htmlextra-export newman-report.html
# With retries
newman run collection.json \
--environment environments/staging.json \
--iteration-count 3 \
--delay-request 200
GitHub Actions
- name: Run API Tests
run: |
newman run collection.json \
--environment environments/staging.json \
--env-var "STAGING_API_KEY=${{ secrets.STAGING_API_KEY }}" \
--reporters cli,junit \
--reporter-junit-export results.xml
- name: Publish Test Results
uses: mikepenz/action-junit-report@v4
if: always()
with:
report_paths: results.xml
Exporting Collection to Code
Postman collections are stored in Git as JSON. Changes are tracked via diff. Postman also supports direct GitHub synchronization.
Implementation Timeline
Developing a collection with tests for a typical REST API (30–50 endpoints): 4–7 days.







