API Testing interview question
How do you test pagination?
Short answer
Know the style first (offset/limit or cursor). Then test page size defaults and limits, first/last/empty pages, invalid parameters, metadata and links, no duplicates or gaps when walking all pages, stable ordering with ties, and what happens when data changes between page requests.
Answer
Start with the design
Ask which style the API uses, because the risks differ:
- Offset/limit or page/size (
?page=3&size=20): simple, supports jumping to a page, but rows shift when data is inserted or deleted between requests, causing duplicates or skipped items. Deep offsets can also be slow. - Cursor or keyset (
?limit=20&after=eyJpZCI6MTIzfQ): stable under inserts and fast, but no random access, and the cursor is opaque and must be validated.
Also note what metadata is returned: total, hasNext, nextCursor, or Link headers.
Test cases
Defaults and limits
- No parameters: default page size applied, documented.
sizeat the maximum, and above it: capped or rejected with 400, never “return a million rows”.size=1: works, useful for exercising many pages with little data.
Boundaries
- First page, last full page, last partial page.
- Exactly N×size items so the last page is full; check
hasNextis false and no extra empty page is advertised. - A page beyond the end: empty list with 200 (or the documented behaviour), not 500.
- Empty collection:
items: [],total: 0.
Invalid input
page=0,page=-1,size=0,size=abc, very large numbers.- A tampered, expired or base64-garbage cursor: 400, not 500 and not a different user’s data.
Correctness across pages
This is the most valuable test: seed a known dataset, walk every page and assert the union equals the dataset with no duplicates.
Set<String> seen = new HashSet<>();
String cursor = null;
do {
var req = given().queryParam("limit", 25);
if (cursor != null) req.queryParam("after", cursor);
Response res = req.when().get("/orders").then().statusCode(200).extract().response();
List<String> ids = res.jsonPath().getList("items.id", String.class);
for (String id : ids) {
assertTrue(seen.add(id), "duplicate id across pages: " + id);
}
cursor = res.jsonPath().getString("nextCursor");
} while (cursor != null);
assertEquals(seededIds, seen);
Ordering
- Results follow the requested sort.
- Ties: if 50 orders share the same
createdAt, sorting only by that field gives a non-deterministic order across pages. The API needs a tiebreaker (usually the id). Seed ties deliberately to catch this.
Data changing during traversal
Insert or delete an item between fetching page 1 and page 2. With offset pagination you may see a duplicate or skip one; decide with the team whether that is acceptable and document it. With cursor pagination, existing items should not be duplicated or skipped.
Combined with filters and security
- Pagination plus filters:
totalreflects the filtered count. - A cursor from user A used by user B must not reveal A’s data.
- Response time for deep pages, if offset is used on large tables.
What interviewers look for
- Asking which pagination style is used before listing tests.
- Boundary and invalid-parameter cases, including max page size.
- Walking all pages to check for duplicates and gaps.
- Awareness of unstable ordering with ties and data changes mid-traversal.
A strong answer covers
- Distinguishes offset/page-based from cursor/keyset pagination
- Boundary tests: default size, max limit, first, last, empty and beyond-last pages
- Invalid parameter handling (negative, zero, non-numeric, tampered cursor)
- Walk all pages: no duplicates or missing items, total count matches
- Stable ordering and consistency when data changes between requests