You know the syntax. You know the assertions. Now let's talk about what to actually test. Most junior testers only write happy-path tests — valid input, expected output. That catches maybe 30% of bugs. The other 70% hide in edge cases, invalid inputs, and structural changes.
Negative testing = testing what happens when things go WRONG. Empty fields, wrong types, invalid IDs, expired tokens. If your API doesn't handle bad input gracefully, attackers will find out before your testers do.
// Negative test: Missing required field
// POST /users with body: { "name": "John" } (missing email)
pm.test("Missing email returns 400", function () {
pm.response.to.have.status(400);
});
pm.test("Error message mentions email", function () {
const error = pm.response.json();
pm.expect(error.message).to.include("email");
});
// Negative test: Invalid data type
// POST /users with body: { "email": 12345, "name": "John" }
pm.test("Invalid email type returns 400", function () {
pm.response.to.have.status(400);
});
// Negative test: Non-existent resource
// GET /users/99999
pm.test("Non-existent user returns 404", function () {
pm.response.to.have.status(404);
});Boundaries are where bugs live. If a field accepts 1-100 characters — test 0, 1, 100, and 101. If age must be 18-65 — test 17, 18, 65, and 66. The spec says "max 50 items per page" — what happens at 50? At 51?
// Boundary test: Pagination limit
// GET /posts?_limit=0
pm.test("Zero limit returns empty array or error", function () {
const response = pm.response.json();
pm.expect(response).to.be.an("array");
pm.expect(response).to.have.lengthOf(0);
});
// GET /posts?_limit=101 (max is 100)
pm.test("Over-limit is capped at max", function () {
const response = pm.response.json();
pm.expect(response.length).to.be.at.most(100);
});
// Boundary test: String length
// POST /users with name = "A" (1 char — minimum)
pm.test("Single character name is accepted", function () {
pm.response.to.have.status(201);
});
// POST /users with name = "A".repeat(256) (too long)
pm.test("Oversized name returns 400", function () {
pm.response.to.have.status(400);
});You don't always know what VALUES the API will return. But you know the STRUCTURE — which keys should exist, what types they should be. Structure validation catches schema drift — when a developer renames a field or changes a type without telling anyone.
// Schema/structure validation for a user object
const user = pm.response.json();
pm.test("User has correct structure", function () {
// Required fields exist
pm.expect(user).to.have.property("id");
pm.expect(user).to.have.property("name");
pm.expect(user).to.have.property("email");
pm.expect(user).to.have.property("createdAt");
// Types are correct
pm.expect(user.id).to.be.a("number");
pm.expect(user.name).to.be.a("string");
pm.expect(user.email).to.be.a("string");
pm.expect(user.createdAt).to.be.a("string");
// Email format check
pm.expect(user.email).to.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
});
pm.test("Unwanted fields are absent", function () {
pm.expect(user).to.not.have.property("password");
pm.expect(user).to.not.have.property("ssn");
pm.expect(user).to.not.have.property("internalId");
});// Validate every item in an array response
const posts = pm.response.json();
pm.test("Every post has required fields", function () {
posts.forEach(function (post, index) {
pm.expect(post, `Post at index ${index}`).to.have.all.keys(
"userId", "id", "title", "body"
);
});
});
pm.test("All IDs are unique", function () {
const ids = posts.map(p => p.id);
const uniqueIds = [...new Set(ids)];
pm.expect(ids.length).to.eql(uniqueIds.length);
});
pm.test("Posts are sorted by ID ascending", function () {
for (let i = 1; i < posts.length; i++) {
pm.expect(posts[i].id).to.be.above(posts[i - 1].id);
}
});Key Point: A good test suite has 3 types of tests: happy path (valid input), negative tests (invalid input), and structure validation (correct shape). Skip any one and you're leaving bugs on the table.
Don't hardcode test data for dynamic APIs. If you assert pm.expect(response.name).to.eql("John") on a search endpoint that returns different results each time — your test will be flaky. Assert structure and types, not exact values, for dynamic endpoints.
Q: What is negative testing in API testing? Give examples.
A: Negative testing verifies that the API handles invalid inputs correctly. Examples: sending a request without required fields (expect 400), using an expired auth token (expect 401), accessing a resource without permission (expect 403), requesting a non-existent resource (expect 404), sending wrong data types like a string where a number is expected (expect 400). Good negative tests also validate the error response body — checking that it contains a meaningful error message, not just the status code.
Key Point: Cover three test types: happy path, negative tests, and structure validation. Use the 8-point checklist to ensure complete coverage for every endpoint.