Đang tải...

Lửng Lọc Lõi

Đeo kính để soi Bug cho rõ, nhíu mày để nhắc Dev sửa cho kỹ. Với tôi, 'chạy được' thôi là chưa đủ! 🧐💻


0

Postman kiểm thử phân trang: assertion cho page, limit và danh sách rỗng

Lửng Lọc Lõi
Lửng Lọc Lõi

6 giờ tới · 1 phút đọc

Contract API giả định và cách đọc trước khi test

Bài này dùng một API giả định có contract rõ ràng. Mọi ví dụ request, response và assertion đều dựa trên contract này - không phải kết quả đo thật.

Endpoint giả định:

GET /api/products?page={page}&limit={limit}

Response contract (giả định):

{
  "data": [...],
  "meta": {
    "page": 1,
    "limit": 10,
    "total": 95,
    "totalPages": 10
  }
}

Các trường cần kiểm tra:

Trường Kiểu Ý nghĩa
data Array Danh sách bản ghi trang hiện tại
meta.page Number Số trang hiện tại (bắt đầu từ 1)
meta.limit Number Số bản ghi tối đa mỗi trang
meta.total Number Tổng số bản ghi toàn bộ
meta.totalPages Number Tổng số trang = ceil(total / limit)

Tại sao phải đọc contract trước? Mỗi API có thể dùng tên field khác nhau: items, records, results, hay pageSize thay cho limit. Assertion sẽ fail nếu bạn hardcode tên field sai.

348171 Đọc contract trước, viết assertion sau - không đoán tên field

Nếu API chưa có tài liệu, bước đầu là gửi một request thủ công, quan sát response thực tế và ghi lại cấu trúc. Bước này nằm ngoài phạm vi bài - bài này tập trung vào phần viết assertion sau khi contract đã rõ.


Positive assertions: page đúng, limit đúng, data có phần tử

Positive assertion kiểm tra rằng khi request hợp lệ, response trả về đúng như contract. Dưới đây là script viết trong tab Tests của Postman (Hướng dẫn Tests tab - Postman Learning Center).

Request giả định: GET /api/products?page=1&limit=10

Response mong đợi (giả định): meta.page = 1, meta.limit = 10, data.length <= 10

// Lấy response body dưới dạng JSON
const res = pm.response.json();

pm.test("Status 200", () => {
  pm.response.to.have.status(200);
});

pm.test("meta.page khớp query param", () => {
  pm.expect(res.meta.page).to.eql(1);
});

pm.test("meta.limit khớp query param", () => {
  pm.expect(res.meta.limit).to.eql(10);
});

pm.test("data là array", () => {
  pm.expect(res.data).to.be.an("array");
});

pm.test("data.length <= limit", () => {
  pm.expect(res.data.length).to.be.at.most(res.meta.limit);
});

pm.test("meta.total là số nguyên dương", () => {
  pm.expect(res.meta.total).to.be.a("number").and.to.be.above(0);
});

pm.test("meta.totalPages khớp ceil(total/limit)", () => {
  const expected = Math.ceil(res.meta.total / res.meta.limit);
  pm.expect(res.meta.totalPages).to.eql(expected);
});

348172 Tab Tests trong Postman - nơi đặt toàn bộ assertion script

Cách tự kiểm tra: Chạy request, mở tab Test Results ở response panel. Mỗi dòng pm.test(...) sẽ hiện PASS hoặc FAIL kèm thông báo lỗi nếu có.

Một điểm hay bị bỏ sót: kiểm tra data.length <= limit thay vì === limit. Trang cuối cùng thường có ít bản ghi hơn limit, nên dùng at.most thay vì eql để tránh false negative.


Negative assertions: page vượt giới hạn và limit không hợp lệ

Negative assertion kiểm tra hành vi của API khi nhận input không hợp lệ. Đây là phần nhiều tester bỏ qua, nhưng lại hay phát hiện bug thật.

Case 1: page vượt quá totalPages

Request giả định: GET /api/products?page=9999&limit=10

Có hai behavior hợp lệ tùy contract:

  • Option A: Trả về 200 với data: [] và meta.page = 9999
  • Option B: Trả về 404 hoặc 400

Bạn cần hỏi dev hoặc đọc API doc để biết behavior nào được chọn. Ví dụ dưới dùng Option A (phổ biến hơn với REST API phân trang):

const res = pm.response.json();

pm.test("Status 200 khi page vượt giới hạn", () => {
  pm.response.to.have.status(200);
});

pm.test("data rỗng khi page vượt totalPages", () => {
  pm.expect(res.data).to.be.an("array").and.to.be.empty;
});

pm.test("meta.page phản ánh đúng query param", () => {
  pm.expect(res.meta.page).to.eql(9999);
});

348173 Cùng một API, behavior khác nhau tùy contract - luôn xác nhận trước khi viết assertion

Case 2: limit âm hoặc bằng 0

Request giả định: GET /api/products?page=1&limit=-1

API thường trả về 400 Bad Request trong trường hợp này:

pm.test("Status 400 khi limit không hợp lệ", () => {
  pm.response.to.have.status(400);
});

pm.test("Response có field error", () => {
  const res = pm.response.json();
  pm.expect(res).to.have.property("error");
});

Case 3: limit vượt giá trị tối đa cho phép

Nếu API giới hạn limit tối đa là 100 (giả định), gửi limit=500 nên trả về 400 hoặc server tự cap về 100:

// Nếu API tự cap limit về max (giả định max = 100)
const res = pm.response.json();

pm.test("meta.limit không vượt giá trị tối đa", () => {
  pm.expect(res.meta.limit).to.be.at.most(100);
});

Lưu ý giới hạn: Giá trị 100 trong ví dụ trên là giả định. Giá trị thực tế phụ thuộc vào từng API. Không hardcode số này mà không đọc contract.


Assertion cho danh sách rỗng hợp lệ

Danh sách rỗng (data: []) là case đặc biệt: không phải lỗi, nhưng cần assertion riêng. Ví dụ: tìm kiếm sản phẩm theo keyword không tồn tại, hoặc filter theo category chưa có bản ghi.

Request giả định: GET /api/products?page=1&limit=10&category=nonexistent

Behavior mong đợi (theo contract giả định): 200 OK, data: [], meta.total = 0

const res = pm.response.json();

pm.test("Status 200 khi không có bản ghi", () => {
  pm.response.to.have.status(200);
});

pm.test("data là mảng rỗng", () => {
  pm.expect(res.data).to.be.an("array").and.to.have.lengthOf(0);
});

pm.test("meta.total bằng 0", () => {
  pm.expect(res.meta.total).to.eql(0);
});

pm.test("meta.totalPages bằng 0", () => {
  pm.expect(res.meta.totalPages).to.eql(0);
});

pm.test("meta.page vẫn là 1", () => {
  pm.expect(res.meta.page).to.eql(1);
});

348174 Danh sách rỗng không phải lỗi - phân biệt rõ để assertion không bị false fail

Tại sao cần kiểm tra meta.totalPages = 0 thay vì chỉ kiểm tra data.length? Vì một số backend bug trả về data: [] nhưng meta.total vẫn giữ giá trị cũ từ cache, làm client hiển thị phân trang sai.

Lỗi thường gặp: Viết pm.expect(res.data).to.be.empty mà không kiểm tra type trước. Nếu API trả về data: null thay vì data: [], assertion này sẽ pass sai. Dùng kết hợp .to.be.an("array").and.to.be.empty để chắc chắn.


Tổ chức test trong Collection và chạy nhiều case cùng lúc

Viết assertion xong trong một request là bước đầu. Để test nhiều case phân trang một lúc, dùng Collection Runner kết hợp với data file.

Cấu trúc collection gợi ý (giả định)

Products API
├── Pagination
│   ├── GET page=1, limit=10 (positive)
│   ├── GET page=9999, limit=10 (page vượt giới hạn)
│   ├── GET page=1, limit=-1 (limit không hợp lệ)
│   └── GET page=1, limit=10, category=nonexistent (danh sách rỗng)

Dùng biến để tránh hardcode

Thay vì ghi thẳng page=1 trong URL, dùng Postman Variables:

GET {{baseUrl}}/api/products?page={{page}}&limit={{limit}}

Trong tab Pre-request Script, set giá trị động:

pm.variables.set("page", 1);
pm.variables.set("limit", 10);

Hoặc dùng data file (CSV/JSON) khi chạy Collection Runner để test nhiều bộ tham số cùng lúc. Ví dụ file CSV giả định:

page,limit,expectedStatus,expectedDataEmpty
1,10,200,false
9999,10,200,true
1,-1,400,false

348175 Collection Runner với data file - chạy nhiều case phân trang trong một lần

Assertion dùng biến từ data file:

const res = pm.response.json();
const expectedEmpty = pm.iterationData.get("expectedDataEmpty") === "true";

pm.test("Kiểm tra data rỗng theo kịch bản", () => {
  if (expectedEmpty) {
    pm.expect(res.data).to.be.an("array").and.to.be.empty;
  } else {
    pm.expect(res.data).to.be.an("array").and.to.not.be.empty;
  }
});

Giới hạn cần biết: pm.iterationData chỉ hoạt động khi chạy qua Collection Runner hoặc Newman, không hoạt động khi bấm "Send" đơn lẻ. Nếu bạn mới làm quen với Newman (CLI runner cho Postman), xem thêm tài liệu tại Tài liệu Newman - Postman CLI.


Lỗi thường gặp khi viết assertion phân trang

Dưới đây là các lỗi hay gặp, kèm cách sửa. Đây là giả định bài tập minh họa.

1. Dùng eql thay vì at.most cho data.length

// SAI - fail ở trang cuối
pm.expect(res.data.length).to.eql(10);

// ĐÚNG
pm.expect(res.data.length).to.be.at.most(res.meta.limit);

2. Không kiểm tra type trước khi kiểm tra giá trị

// Dễ gây false pass nếu meta là null
pm.expect(res.meta.total).to.eql(0);

// Chắc chắn hơn
pm.expect(res.meta).to.be.an("object");
pm.expect(res.meta.total).to.be.a("number").and.to.eql(0);

3. Hardcode page number trong assertion

// SAI - assertion sẽ fail nếu dùng request khác
pm.expect(res.meta.page).to.eql(1);

// ĐÚNG - đọc lại từ query param thực tế
const urlPage = parseInt(pm.request.url.query.get("page"));
pm.expect(res.meta.page).to.eql(urlPage);

348176 Ba lỗi này chiếm phần lớn assertion fail không mong đợi khi test phân trang

4. Quên kiểm tra totalPages khi total = 0

Nếu meta.total = 0 mà meta.totalPages = 1, đây là bug backend. Kiểm tra cả hai trường khi test case danh sách rỗng.

5. Nhầm giữa 0-indexed và 1-indexed page

Một số API dùng page=0 là trang đầu, số khác dùng page=1. Assertion sẽ fail hoàn toàn nếu bạn dùng sai quy ước. Luôn đọc contract trước.


Tài nguyên tham khảo:

Bài viết dựa trên API giả định để minh họa. Assertion cụ thể cần điều chỉnh theo contract API thực tế của từng dự án.

Trang web dùng cookie để hoạt động và đo hiệu quả quảng cáo. Xem chính sách bảo mật