QA Interview Hub · Knowledge base · Quizzes
API
Scripts and checks in Postman
Postman: variables, scripts, chaining
Variable scopes from wider to narrower: global, collection, environment, data and local. The narrower one overrides the wider, so a variable of the same name from the environment will override a global one. Environments let you run the same collection on dev, stage and prod by simply switching the environment.
A pre-request script runs before the request: generating unique data, getting a token, computing a signature or a timestamp. A post-response script (formerly the Tests tab) runs after the response: checks through pm.test and pm.expect, for example the status, fields and response time. Scripts can be set at the request, folder and collection level.
Chaining is passing data between requests: after creating a user I save their ID with pm.environment.set('userId', json.id). Following requests use {{userId}}. A collection is run through the Collection Runner with CSV or JSON for data-driven tests, or through Newman on CI.
Pre-request, post-response and basic checks
A pre-request script runs before the request is sent (prepare data, a token), post-response runs after (check the response, save values). The order: the collection's script, then the folder's, then the request's. The language is JavaScript, and assertions are Chai through pm.expect.
A basic set of checks:
pm.test('Status 201', () => pm.response.to.have.status(201));
pm.test('Response time < 800 ms', () => {
pm.expect(pm.response.responseTime).to.be.below(800);
});
pm.test('JSON content type', () => {
pm.response.to.have.header('Content-Type');
pm.expect(pm.response.headers.get('Content-Type')).to.include('application/json');
});
const body = pm.response.json();
pm.test('Body fields', () => {
pm.expect(body).to.have.property('id');
pm.expect(body.status).to.eql('pending');
pm.expect(body.amount).to.be.a('number').and.eql(150);
pm.expect(body).to.not.have.property('cardNumber'); // sensitive data isn't returned
});
Each pm.test is a separate line in the report, so it is better to have several small tests with clear names than one big one. Then the Runner report immediately shows what exactly broke.
In an interview: Pre-request prepares data and the token, post-response checks the response and saves values. I check the status, time, Content-Type, key fields and the absence of sensitive data, each check in a separate pm.test.
Schema validation and a chain of requests
Schema validation checks the whole structure: required fields, types, allowed values.
const schema = {
type: 'object',
required: ['id', 'status', 'amount', 'currency'],
properties: {
id: { type: 'string' },
status: { enum: ['pending', 'completed', 'failed'] },
amount: { type: 'number', exclusiveMinimum: 0 },
currency: { type: 'string', pattern: '^[A-Z]{3}$' }
},
additionalProperties: false
};
pm.test('Schema is valid', () => pm.response.to.have.jsonSchema(schema));
additionalProperties: false catches the situation where the backend suddenly started returning a new field, for example an internal identifier. It is both protection against data leakage and a signal of an undocumented contract change.
A request chain is passing data from one request to the next:
// post-response in POST /accounts
pm.environment.set('accountId', pm.response.json().id);
// the next request: GET {{baseUrl}}/accounts/{{accountId}}
In an interview: A schema checks the whole response structure in one test, and additionalProperties: false catches extra fields. I pass data between requests through variables: I save the id in post-response and use {{accountId}} in the next request.
Useful commands and a strong test
Useful commands:
pm.sendRequest(...) sends a helper request from a script, for example to get a token in pre-request.pm.execution.setNextRequest('Name') changes the order in the Runner; null stops the run. In old collections you encounter postman.setNextRequest.pm.environment.unset('token') cleans up a variable after yourself.console.log(...) prints to the Postman Console (at the bottom of the window): there you see the raw request and response, it is the main debugging tool.
The Postman Console is especially useful when a variable wasn't substituted: it shows the final URL and headers, and it is immediately clear whether the request went with {{token}} literally or with the real value.
A weak test vs a strong one. Checking only status 200 will miss an empty or wrong array. The minimum is the status, the schema and key values. For a write, also the following GET, to make sure the data was really saved. For example, after PATCH /accounts/42 with a new name I do GET /accounts/42 and check that only the name field changed and the rest stayed as it was.
In an interview: A test that checks only 200 guarantees almost nothing. I check the status, the schema and key values, and after a write I do a GET to confirm the change was saved.