Tóm tắt
Một trường hợp kiểm thử (test case) là một kịch bản kiểm thử đơn lẻ, cụ thể để kiểm tra một hành vi hoặc yêu cầu cụ thể, trong khi bộ kiểm thử (test suite) là một tập hợp các trường hợp kiểm thử liên quan được nhóm lại với nhau để thực hiện có tổ chức. Các trường hợp kiểm thử xác định những gì cần kiểm thử và cách kiểm thử. Các bộ kiểm thử tổ chức nhiều trường hợp kiểm thử thành các nhóm logic để quy trình kiểm thử hiệu quả.
Giới thiệu
Bạn đang xây dựng một API. Bạn viết bài kiểm thử đầu tiên. Rồi một bài nữa. Chẳng bao lâu, bạn có 50 bài kiểm thử nằm rải rác trong các tệp khác nhau. Bài nào kiểm tra xác thực? Bài nào chạy trước khi triển khai? Làm thế nào để bạn chỉ chạy các bài kiểm thử quan trọng?
Sự nhầm lẫn này xảy ra khi các nhà phát triển không hiểu sự khác biệt giữa trường hợp kiểm thử (test case) và bộ kiểm thử (test suite). Một cuộc khảo sát năm 2023 với 1.200 nhà phát triển cho thấy 67% gặp khó khăn trong việc tổ chức kiểm thử, dẫn đến các quy trình CI/CD chậm hơn và khó gỡ lỗi hơn. Hai khái niệm này hình thành nền tảng của việc kiểm thử có tổ chức, nhưng chúng thường được sử dụng thay thế cho nhau hoặc bị hiểu sai.
Hiểu rõ sự khác biệt giúp bạn tổ chức các bài kiểm thử một cách hợp lý, chạy chúng hiệu quả và duy trì chúng khi API của bạn phát triển. Cho dù bạn đang kiểm thử bằng Apidog hay một công cụ khác, việc biết khi nào nên tạo một trường hợp kiểm thử mới so với khi nào nên nhóm các trường hợp vào các bộ kiểm thử sẽ làm cho quy trình kiểm thử của bạn nhanh hơn và đáng tin cậy hơn.
Trong hướng dẫn này, bạn sẽ tìm hiểu sự khác biệt chính xác giữa các trường hợp kiểm thử và bộ kiểm thử, xem các ví dụ kiểm thử API thực tế và khám phá cách tổ chức cả hai để đạt hiệu quả tối đa. Đến cuối cùng, bạn sẽ biết chính xác cách cấu trúc các bài kiểm thử API của mình cho bất kỳ quy mô dự án nào.
Trường hợp kiểm thử là gì?
Một trường hợp kiểm thử là một kịch bản kiểm thử đơn lẻ, cụ thể xác minh một hành vi hoặc yêu cầu của phần mềm của bạn. Hãy nghĩ nó như một câu hỏi bạn đang hỏi mã của mình: "Cái này có hoạt động đúng không?"

Mỗi trường hợp kiểm thử bao gồm:
- ID kiểm thử: Định danh duy nhất (ví dụ: TC_001)
- Mô tả kiểm thử: Những gì bạn đang kiểm thử
- Điều kiện tiên quyết: Thiết lập cần thiết trước khi kiểm thử
- Các bước kiểm thử: Các hành động cần thực hiện
- Kết quả mong đợi: Điều gì sẽ xảy ra
- Kết quả thực tế: Điều gì đã thực sự xảy ra
- Trạng thái: Đạt hoặc không đạt
Giải phẫu một trường hợp kiểm thử
Đây là một trường hợp kiểm thử đơn giản cho một điểm cuối API:
Test Case ID: TC_AUTH_001
Title: Xác minh đăng nhập người dùng với thông tin đăng nhập hợp lệ
Preconditions: Tài khoản người dùng tồn tại trong cơ sở dữ liệu
Test Steps:
1. Gửi yêu cầu POST tới /api/auth/login
2. Bao gồm email và mật khẩu hợp lệ trong nội dung yêu cầu
3. Kiểm tra mã trạng thái phản hồi
4. Xác minh mã thông báo JWT được trả về
Expected Result:
- Mã trạng thái: 200
- Phản hồi chứa mã thông báo JWT hợp lệ
- Mã thông báo hết hạn sau 24 giờ
Actual Result: [Sẽ được điền trong quá trình thực hiện]
Status: [Đạt/Không đạt]
Các trường hợp kiểm thử là nguyên tử. Chúng chỉ kiểm tra một thứ duy nhất. Nếu trường hợp kiểm thử của bạn kiểm tra đăng nhập VÀ cập nhật hồ sơ, hãy chia nó thành hai trường hợp kiểm thử.
Ví dụ trường hợp kiểm thử trong mã
Đây là cách trường hợp kiểm thử tương tự trông như thế nào trong JavaScript sử dụng Jest:
describe('Authentication API', () => {
test('TC_AUTH_001: should login user with valid credentials', async () => {
const response = await fetch('https://api.example.com/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
password: 'SecurePass123'
})
});
expect(response.status).toBe(200);
const data = await response.json();
expect(data.token).toBeDefined();
expect(data.expiresIn).toBe(86400); // 24 hours in seconds
});
});
Hãy chú ý cách trường hợp kiểm thử này tập trung vào một kịch bản: đăng nhập thành công. Nó không kiểm tra đăng nhập thất bại, đặt lại mật khẩu hoặc đăng xuất. Những trường hợp đó sẽ là các trường hợp kiểm thử riêng biệt.
Tại sao các trường hợp kiểm thử lại quan trọng
Các trường hợp kiểm thử mang lại cho bạn:
- Khả năng truy vết: Ánh xạ mỗi bài kiểm thử với một yêu cầu cụ thể
- Khả năng lặp lại: Chạy cùng một bài kiểm thử một cách nhất quán
- Tài liệu: Các bài kiểm thử đóng vai trò là tài liệu sống
- Gỡ lỗi: Xác định chính xác lỗi xảy ra khi một bài kiểm thử thất bại
Nếu không có các trường hợp kiểm thử rõ ràng, bạn sẽ có các bài kiểm thử mơ hồ kiểm tra nhiều thứ cùng lúc. Khi chúng thất bại, bạn sẽ lãng phí thời gian để tìm ra phần nào bị hỏng.
Bộ kiểm thử là gì?
Bộ kiểm thử (test suite) là một tập hợp các trường hợp kiểm thử được nhóm lại với nhau để thực hiện có tổ chức. Nếu các trường hợp kiểm thử là các câu hỏi riêng lẻ, thì bộ kiểm thử là bài kiểm tra chứa các câu hỏi liên quan.

Các bộ kiểm thử tổ chức các trường hợp kiểm thử theo:
- Tính năng: Tất cả các bài kiểm thử cho xác thực người dùng
- Ưu tiên: Các bài kiểm thử quan trọng phải vượt qua trước khi triển khai
- Loại: Kiểm thử sơ bộ (smoke tests), kiểm thử hồi quy (regression tests), kiểm thử tích hợp (integration tests)
- Môi trường: Kiểm thử cho môi trường thử nghiệm (staging) so với môi trường sản xuất (production)
- Thời gian thực hiện: Các bài kiểm thử nhanh so với các bài kiểm thử chậm
Cấu trúc bộ kiểm thử
Đây là cách các bộ kiểm thử tổ chức các trường hợp kiểm thử:
Bộ kiểm thử: Mô-đun xác thực
├── Trường hợp kiểm thử 1: Đăng nhập bằng thông tin đăng nhập hợp lệ
├── Trường hợp kiểm thử 2: Đăng nhập bằng mật khẩu không hợp lệ
├── Trường hợp kiểm thử 3: Đăng nhập bằng email không tồn tại
├── Trường hợp kiểm thử 4: Đăng nhập bằng mã thông báo đã hết hạn
├── Trường hợp kiểm thử 5: Đăng xuất thành công
└── Trường hợp kiểm thử 6: Làm mới mã thông báo truy cập
Bộ kiểm thử: Mô-đun hồ sơ người dùng
├── Trường hợp kiểm thử 1: Lấy hồ sơ người dùng
├── Trường hợp kiểm thử 2: Cập nhật thông tin hồ sơ
├── Trường hợp kiểm thử 3: Tải ảnh hồ sơ
└── Trường hợp kiểm thử 4: Xóa tài khoản người dùng
Mỗi bộ kiểm thử chứa nhiều trường hợp kiểm thử liên quan. Bạn có thể chạy toàn bộ một bộ kiểm thử cùng lúc hoặc chọn các trường hợp kiểm thử riêng lẻ để chạy.
Ví dụ bộ kiểm thử trong mã
Đây là cách các bộ kiểm thử trông như thế nào trong JavaScript:
// Bộ kiểm thử xác thực
describe('Authentication API Test Suite', () => {
test('TC_AUTH_001: Login with valid credentials', async () => {
// Triển khai kiểm thử
});
test('TC_AUTH_002: Login with invalid password', async () => {
// Triển khai kiểm thử
});
test('TC_AUTH_003: Login with non-existent email', async () => {
// Triển khai kiểm thử
});
test('TC_AUTH_004: Logout successfully', async () => {
// Triển khai kiểm thử
});
});
// Bộ kiểm thử hồ sơ người dùng
describe('User Profile API Test Suite', () => {
test('TC_PROFILE_001: Get user profile', async () => {
// Triển khai kiểm thử
});
test('TC_PROFILE_002: Update profile information', async () => {
// Triển khai kiểm thử
});
});
Các khối describe() tạo ra các bộ kiểm thử. Mỗi test() bên trong là một trường hợp kiểm thử. Bạn có thể chạy tất cả các bài kiểm thử xác thực bằng một lệnh hoặc chạy toàn bộ tệp kiểm thử.
Các bộ kiểm thử lồng nhau
Các bộ kiểm thử có thể chứa các bộ kiểm thử khác cho các dự án phức tạp:
describe('API Test Suite', () => {
describe('Authentication', () => {
describe('Login', () => {
test('with valid credentials', () => {});
test('with invalid password', () => {});
});
describe('Registration', () => {
test('with valid data', () => {});
test('with duplicate email', () => {});
});
});
describe('User Management', () => {
test('get user list', () => {});
test('update user role', () => {});
});
});
Điều này tạo ra một hệ thống phân cấp: Bộ chính → Các bộ con → Các trường hợp kiểm thử. Cấu trúc này phản ánh kiến trúc API của bạn.
Điểm khác biệt chính giữa bộ kiểm thử và trường hợp kiểm thử
Dưới đây là bảng so sánh rõ ràng:
| Khía cạnh | Trường hợp kiểm thử | Bộ kiểm thử |
|---|---|---|
| Định nghĩa | Kịch bản kiểm thử đơn lẻ | Tập hợp các trường hợp kiểm thử |
| Phạm vi | Kiểm thử một hành vi cụ thể | Kiểm thử nhiều hành vi liên quan |
| Mức độ chi tiết | Nguyên tử (không thể chia nhỏ) | Hợp thành (chứa nhiều mục) |
| Thực hiện | Chạy một bài kiểm thử | Chạy nhiều bài kiểm thử |
| Mục đích | Xác minh một yêu cầu | Tổ chức và nhóm các bài kiểm thử |
| Kết quả | Đạt hoặc Không đạt | Tóm tắt tất cả các kết quả kiểm thử |
| Ví dụ | "Đăng nhập bằng thông tin đăng nhập hợp lệ" | "Các bài kiểm thử mô-đun xác thực" |
| Mã | Một hàm test() hoặc it() |
Một khối describe() hoặc suite() |
| Khả năng tái sử dụng | Có thể được thêm vào nhiều bộ kiểm thử | Có thể chứa các trường hợp kiểm thử được chia sẻ |
| Bảo trì | Cập nhật một bài kiểm thử | Cập nhật nhiều bài kiểm thử cùng lúc |
Sự tương đồng về thùng chứa
Hãy nghĩ theo cách này:
- Trường hợp kiểm thử = Một tệp đơn lẻ trong máy tính của bạn
- Bộ kiểm thử = Một thư mục chứa các tệp liên quan
Bạn có thể có các tệp mà không có thư mục (các trường hợp kiểm thử mà không có bộ kiểm thử), nhưng các thư mục giúp tổ chức các tệp (các bộ kiểm thử giúp tổ chức các trường hợp kiểm thử). Bạn cũng có thể có các thư mục bên trong các thư mục (các bộ kiểm thử lồng nhau).
Sự khác biệt trong thực thi
Khi bạn chạy một trường hợp kiểm thử:
# Chạy một bài kiểm thử cụ thể
npm test -- --testNamePattern="Login with valid credentials"
Khi bạn chạy một bộ kiểm thử:
# Chạy tất cả các bài kiểm thử trong bộ Authentication
npm test -- --testPathPattern="authentication"
Các bộ kiểm thử cho phép bạn chạy các nhóm bài kiểm thử liên quan mà không cần chạy toàn bộ bộ sưu tập kiểm thử của bạn.
Cách các bộ kiểm thử và trường hợp kiểm thử hoạt động cùng nhau
Các trường hợp kiểm thử và bộ kiểm thử không phải là những khái niệm cạnh tranh. Chúng hoạt động cùng nhau để tạo ra mã kiểm thử có tổ chức, dễ bảo trì.
Mối quan hệ
Dự án
└── Các bộ kiểm thử (Thư mục)
└── Các trường hợp kiểm thử (Tệp)
└── Các bước kiểm thử (Mã)
Mỗi trường hợp kiểm thử thuộc ít nhất một bộ kiểm thử. Một trường hợp kiểm thử có thể thuộc nhiều bộ kiểm thử:
// smoke-tests.suite.js
describe('Smoke Tests', () => {
test('TC_SMOKE_001: API health check', () => {});
test('TC_SMOKE_002: Database connection', () => {});
test('TC_AUTH_001: Login with valid credentials', () => {}); // Chia sẻ
});
// authentication.suite.js
describe('Authentication Tests', () => {
test('TC_AUTH_001: Login with valid credentials', () => {}); // Chia sẻ
test('TC_AUTH_002: Login with invalid password', () => {});
test('TC_AUTH_003: Password reset flow', () => {});
});
Trường hợp kiểm thử TC_AUTH_001 xuất hiện trong cả bộ kiểm thử sơ bộ và bộ kiểm thử xác thực. Khả năng tái sử dụng này cho phép bạn chạy cùng một bài kiểm thử trong các ngữ cảnh khác nhau mà không bị trùng lặp.
Tích hợp quy trình làm việc
Đây là cách chúng hoạt động trong một quy trình phát triển điển hình:
- Viết các trường hợp kiểm thử cho các tính năng mới
- Nhóm các trường hợp kiểm thử vào các bộ kiểm thử logic
- Chạy các bộ kiểm thử cụ thể trong quá trình phát triển (phản hồi nhanh)
- Chạy tất cả các bộ kiểm thử trước khi triển khai (kiểm tra toàn diện)
- Phân tích kết quả bộ kiểm thử để xác định các khu vực có vấn đề
Chiến lược thực thi
Các tình huống khác nhau đòi hỏi các chiến lược thực thi khác nhau:
# Trong quá trình phát triển: Chạy một trường hợp kiểm thử
npm test -- --testNamePattern="TC_AUTH_001"
# Trước khi commit: Chạy bộ kiểm thử liên quan
npm test -- authentication.test.js
# Trong CI/CD: Chạy tất cả các bộ kiểm thử quan trọng
npm test -- --testPathPattern="(smoke|critical)"
# Trước khi phát hành: Chạy tất cả
npm test
Cách tiếp cận phân lớp này tiết kiệm thời gian. Chạy 5 bài kiểm thử sơ bộ trong 10 giây thay vì 200 bài kiểm thử trong 5 phút trong quá trình phát triển. Lưu toàn bộ bộ kiểm thử cho CI/CD.
Bộ kiểm thử so với trường hợp kiểm thử trong kiểm thử API
Kiểm thử API có những đặc điểm riêng biệt ảnh hưởng đến cách bạn tổ chức các trường hợp kiểm thử và bộ kiểm thử.
Cấu trúc trường hợp kiểm thử API
Các trường hợp kiểm thử API thường xác minh:
- Xác thực yêu cầu: Điểm cuối, phương thức, tiêu đề, nội dung chính xác
- Xác thực phản hồi: Mã trạng thái, nội dung phản hồi, tiêu đề
- Xác thực dữ liệu: Định dạng dữ liệu, giá trị, kiểu dữ liệu chính xác
- Xử lý lỗi: Các thông báo và mã lỗi phù hợp
- Hiệu suất: Thời gian phản hồi trong giới hạn chấp nhận được
Đây là một trường hợp kiểm thử API hoàn chỉnh:
test('TC_USER_001: Create new user via POST /api/users', async () => {
// Sắp xếp
const newUser = {
name: 'John Doe',
email: 'john@example.com',
role: 'user'
};
// Thực hiện
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer test-token'
},
body: JSON.stringify(newUser)
});
const data = await response.json();
// Khẳng định
expect(response.status).toBe(201);
expect(data.id).toBeDefined();
expect(data.name).toBe(newUser.name);
expect(data.email).toBe(newUser.email);
expect(data.createdAt).toBeDefined();
});
Trường hợp kiểm thử này kiểm tra một thao tác API: tạo người dùng. Nó không kiểm tra việc cập nhật, xóa hoặc liệt kê người dùng.
Tổ chức bộ kiểm thử API
Đối với API, hãy tổ chức các bộ kiểm thử theo:
1. Theo điểm cuối
Bộ kiểm thử: /api/users
├── GET /api/users (liệt kê người dùng)
├── POST /api/users (tạo người dùng)
├── GET /api/users/:id (lấy người dùng)
├── PUT /api/users/:id (cập nhật người dùng)
└── DELETE /api/users/:id (xóa người dùng)
2. Theo tính năng
Bộ kiểm thử: Quản lý người dùng
├── Đăng ký người dùng
├── Xác thực người dùng
├── Quản lý hồ sơ
└── Xóa tài khoản
3. Theo loại kiểm thử
Bộ kiểm thử: Kiểm thử sơ bộ (Smoke Tests)
├── Kiểm tra trạng thái API
├── Kết nối cơ sở dữ liệu
└── Các điểm cuối quan trọng phản hồi
Bộ kiểm thử: Kiểm thử tích hợp
├── Luồng đăng ký người dùng
├── Luồng xử lý đơn hàng
└── Luồng xử lý thanh toán
Quản lý bộ kiểm thử Apidog
Apidog giúp việc tổ chức các bộ kiểm thử API trở nên trực quan và dễ hiểu. Thay vì viết mã, bạn xây dựng các trường hợp kiểm thử trong giao diện người dùng đồ họa (GUI) và nhóm chúng vào các bộ kiểm thử bằng cách kéo và thả. Điều này giúp giảm 60% thời gian tạo kiểm thử so với các phương pháp dựa trên mã.
Đây là cách Apidog xử lý việc tổ chức kiểm thử:
Các trường hợp kiểm thử trong Apidog:
Bạn có thể tạo các trường hợp kiểm thử theo nhiều cách:
Trong tab Test Cases của trang chi tiết điểm cuối, nhấp vào + Add Case để tạo thủ công một trường hợp kiểm thử.
Khi thêm một trường hợp kiểm thử, bạn có thể chọn
- Import from Debug Cases để sao chép hoặc di chuyển các trường hợp gỡ lỗi hiện có vào các trường hợp kiểm thử.
- Copy: Sử dụng tùy chọn này khi bạn vẫn cần trường hợp gỡ lỗi để xác thực nhanh nhưng cũng muốn nó là một trường hợp kiểm thử.
- Move: Sử dụng tùy chọn này khi trường hợp gỡ lỗi không còn được sử dụng thường xuyên để gỡ lỗi và chủ yếu được viết để kiểm thử các ngoại lệ. Điều này trực tiếp chuyển đổi nó thành một trường hợp kiểm thử, giúp việc di chuyển nhanh hơn nếu các trường hợp kiểm thử ban đầu được tạo dưới dạng trường hợp gỡ lỗi.
Một trường hợp kiểm thử chứa các thông tin sau:
- Nhóm: Được tổ chức theo mục đích kiểm thử (tích cực, tiêu cực, ranh giới, v.v.).
- Tên trường hợp: Tên của trường hợp kiểm thử.
- Tham số yêu cầu: Các tham số Path, Query, Header và Body form-data.
- Nội dung yêu cầu: Hỗ trợ RAW, JSON, XML, v.v.
- Bộ xử lý trước/sau
- Xác thực phản hồi: Bật/tắt xác thực và chỉ định các thành phần phản hồi cần được xác thực.
Các bộ kiểm thử trong Apidog:
- Khi mở Apidog, điều hướng đến mô-đun
Tests, sau đó tìmTest Suite.
- Nhấp vào nút
+ New(hoặc nhấp vào menu...bên cạnh thư mục và chọnCreate Test Suite). - Điền tên bộ kiểm thử vào cửa sổ bật lên và đặt thông tin cơ bản, chẳng hạn như mức độ ưu tiên.
- Nhấp vào
Continueđể tạo thành công và vào trang thiết kế bộ kiểm thử.
Lợi ích:
- Không yêu cầu viết mã cho các bài kiểm thử cơ bản
- Tổ chức kiểm thử trực quan
- Các khẳng định và xác thực tích hợp sẵn
- Tạo báo cáo kiểm thử tự động
- Tích hợp CI/CD để chạy tự động
Bạn có thể xuất các bộ kiểm thử Apidog sang mã nếu cần, mang lại cho bạn sự linh hoạt giữa kiểm thử dựa trên GUI và kiểm thử dựa trên mã.
Khi nào nên sử dụng trường hợp kiểm thử so với bộ kiểm thử
Việc biết khi nào nên tạo một trường hợp kiểm thử mới so với khi nào nên nhóm các trường hợp vào các bộ kiểm thử là rất quan trọng để có các bài kiểm thử dễ bảo trì.
Tạo một trường hợp kiểm thử mới khi:
- Kiểm thử một yêu cầu mới: Mỗi yêu cầu nên có ít nhất một trường hợp kiểm thử
- Kiểm thử một kịch bản khác: Đăng nhập hợp lệ so với đăng nhập không hợp lệ = hai trường hợp kiểm thử
- Kiểm thử các trường hợp biên: Đầu vào trống, đầu vào tối đa, ký tự đặc biệt
- Kiểm thử các điều kiện lỗi: Lỗi 400, lỗi 500, các kịch bản hết thời gian chờ
- Kiểm thử dữ liệu khác nhau: Các vai trò người dùng khác nhau, các quyền khác nhau
Tạo một bộ kiểm thử mới khi:
- Bạn có 5+ trường hợp kiểm thử liên quan: Nhóm chúng lại để tổ chức
- Kiểm thử một tính năng hoàn chỉnh: Tất cả các bài kiểm thử xác thực cùng nhau
- Tạo một danh mục kiểm thử: Kiểm thử sơ bộ, kiểm thử hồi quy, kiểm thử hiệu suất
- Tổ chức theo mức độ ưu tiên: Kiểm thử quan trọng, ưu tiên cao, ưu tiên thấp
- Tách biệt theo môi trường: Kiểm thử môi trường thử nghiệm, kiểm thử môi trường sản xuất
Các mẫu phản tác dụng cần tránh
Không làm điều này:
// TỆ: Một trường hợp kiểm thử khổng lồ kiểm tra mọi thứ
test('Test entire user flow', () => {
// Kiểm tra đăng ký, đăng nhập, cập nhật hồ sơ và xóa
// Nếu điều này thất bại, phần nào bị hỏng?
});
Thay vào đó, hãy làm điều này:
// TỐT: Các trường hợp kiểm thử riêng biệt trong các bộ có tổ chức
describe('User Management Suite', () => {
test('TC_001: Register new user', () => {});
test('TC_002: Login with credentials', () => {});
test('TC_003: Update user profile', () => {});
});
describe('Content Management Suite', () => {
test('TC_004: Create new post', () => {});
test('TC_005: Delete post', () => {});
});
Không làm điều này:
// TỆ: Quá nhiều bộ kiểm thử lồng nhau
describe('API', () => {
describe('V1', () => {
describe('Users', () => {
describe('Authentication', () => {
describe('Login', () => {
describe('Valid Credentials', () => {
test('with email', () => {});
});
});
});
});
});
});
Thay vào đó, hãy làm điều này:
// TỐT: Lồng nhau hợp lý (tối đa 2-3 cấp)
describe('API V1: User Authentication', () => {
describe('Login', () => {
test('with valid email and password', () => {});
test('with invalid password', () => {});
});
describe('Registration', () => {
test('with valid data', () => {});
});
});
Các phương pháp hay nhất để tổ chức các trường hợp kiểm thử và bộ kiểm thử
Thực hiện theo các chiến lược đã được chứng minh này để giữ cho các bài kiểm thử của bạn có tổ chức và dễ bảo trì.
1. Sử dụng quy ước đặt tên rõ ràng
Trường hợp kiểm thử:
// Tốt: Mô tả và cụ thể
test('should return 200 when user logs in with valid credentials', () => {});
test('should return 401 when password is incorrect', () => {});
test('should return 404 when user does not exist', () => {});
// Xấu: Mơ hồ và không rõ ràng
test('login test', () => {});
test('test 1', () => {});
test('check user', () => {});
Bộ kiểm thử:
// Tốt: Phạm vi và mục đích rõ ràng
describe('Authentication API - Login Endpoint', () => {});
describe('User Profile Management', () => {});
describe('Payment Processing Integration Tests', () => {});
// Xấu: Quá chung chung
describe('Tests', () => {});
describe('API', () => {});
describe('Stuff', () => {});
2. Giữ các trường hợp kiểm thử độc lập
Mỗi trường hợp kiểm thử nên chạy độc lập mà không phụ thuộc vào các bài kiểm thử khác:
// TỆ: Các bài kiểm thử phụ thuộc vào nhau
let userId;
test('create user', async () => {
const response = await createUser();
userId = response.id; // Lưu trạng thái
});
test('update user', async () => {
await updateUser(userId); // Phụ thuộc vào bài kiểm thử trước đó
});
// TỐT: Mỗi bài kiểm thử là độc lập
test('create user', async () => {
const response = await createUser();
expect(response.status).toBe(201);
await cleanup(response.id); // Dọn dẹp sau kiểm thử
});
test('update user', async () => {
const user = await createUser(); // Tạo dữ liệu kiểm thử riêng
const response = await updateUser(user.id);
expect(response.status).toBe(200);
await cleanup(user.id);
});
3. Tổ chức các bộ kiểm thử theo tính năng hoặc mô-đun
Phản ánh cấu trúc API của bạn trong tổ chức kiểm thử của bạn:
src/
├── auth/
│ ├── login.js
│ └── register.js
├── users/
│ ├── profile.js
│ └── settings.js
└── posts/
├── create.js
└── delete.js
tests/
├── auth/
│ ├── login.test.js (Bộ kiểm thử)
│ └── register.test.js (Bộ kiểm thử)
├── users/
│ ├── profile.test.js (Bộ kiểm thử)
│ └── settings.test.js (Bộ kiểm thử)
└── posts/
├── create.test.js (Bộ kiểm thử)
└── delete.test.js (Bộ kiểm thử)
4. Sử dụng các hook thiết lập và dọn dẹp
Giảm trùng lặp với các hook trước/sau:
describe('User API Test Suite', () => {
let authToken;
let testUser;
// Chạy một lần trước tất cả các bài kiểm thử trong bộ này
beforeAll(async () => {
authToken = await getAuthToken();
});
// Chạy trước mỗi trường hợp kiểm thử
beforeEach(async () => {
testUser = await createTestUser();
});
// Chạy sau mỗi trường hợp kiểm thử
afterEach(async () => {
await deleteTestUser(testUser.id);
});
// Chạy một lần sau tất cả các bài kiểm thử trong bộ này
afterAll(async () => {
await revokeAuthToken(authToken);
});
test('TC_001: Get user profile', async () => {
// testUser và authToken có sẵn
});
test('TC_002: Update user profile', async () => {
// testUser và authToken có sẵn
});
});
5. Gắn thẻ bài kiểm thử để thực thi linh hoạt
Sử dụng thẻ hoặc danh mục để chạy các nhóm kiểm thử cụ thể:
describe('Authentication Suite', () => {
test('[smoke] API health check', () => {});
test('[critical] Login with valid credentials', () => {});
test('[regression] Login with expired token', () => {});
test('[edge-case] Login with special characters in password', () => {});
});
// Chỉ chạy các bài kiểm thử sơ bộ
// npm test -- --testNamePattern="smoke"
// Chạy các bài kiểm thử quan trọng
// npm test -- --testNamePattern="critical"
6. Duy trì hệ thống phân cấp bộ kiểm thử
Tạo một hệ thống phân cấp rõ ràng cho các dự án lớn:
Cấp độ 1: Loại kiểm thử (Sơ bộ, Tích hợp, E2E)
└── Cấp độ 2: Mô-đun tính năng (Xác thực, Người dùng, Đơn hàng)
└── Cấp độ 3: Chức năng cụ thể (Đăng nhập, Đăng ký)
└── Cấp độ 4: Các trường hợp kiểm thử (Hợp lệ, Không hợp lệ, Trường hợp biên)
Ví dụ:
describe('[Integration] User Management', () => {
describe('Authentication', () => {
describe('Login', () => {
test('with valid credentials', () => {});
test('with invalid password', () => {});
test('with non-existent email', () => {});
});
});
});
Những sai lầm thường gặp cần tránh
1. Tạo các trường hợp kiểm thử quá rộng
Vấn đề:
test('test user functionality', () => {
// Kiểm tra đăng ký, đăng nhập, cập nhật hồ sơ và xóa
// Nếu điều này thất bại, phần nào bị hỏng?
});
Giải pháp:
test('should register new user', () => {});
test('should login registered user', () => {});
test('should update user profile', () => {});
test('should delete user account', () => {});
2. Không nhóm các trường hợp kiểm thử liên quan
Vấn đề:
test('login test 1', () => {});
test('profile test 1', () => {});
test('login test 2', () => {});
test('order test 1', () => {});
test('profile test 2', () => {});
Giải pháp:
describe('Login Tests', () => {
test('test 1', () => {});
test('test 2', () => {});
});
describe('Profile Tests', () => {
test('test 1', () => {});
test('test 2', () => {});
});
3. Tạo quá nhiều bộ kiểm thử lồng nhau
Vấn đề:
describe('API', () => {
describe('Version 1', () => {
describe('Users', () => {
describe('Profile', () => {
describe('Update', () => {
test('with valid data', () => {});
});
});
});
});
});
Giải pháp:
describe('API V1: User Profile', () => {
test('should update profile with valid data', () => {});
});
4. Bỏ qua thứ tự thực thi kiểm thử
Vấn đề:
describe('User Flow', () => {
test('delete user', () => {}); // Chạy đầu tiên
test('create user', () => {}); // Chạy thứ hai
test('update user', () => {}); // Chạy thứ ba
});
Giải pháp:
describe('User Flow', () => {
test('1. create user', () => {});
test('2. update user', () => {});
test('3. delete user', () => {});
});
// Hoặc sử dụng beforeEach để đảm bảo thiết lập đúng
5. Không sử dụng tên mô tả
Vấn đề:
describe('Suite 1', () => {
test('test 1', () => {});
test('test 2', () => {});
});
Giải pháp:
describe('Authentication API Tests', () => {
test('should return JWT token on successful login', () => {});
test('should return 401 on invalid credentials', () => {});
});
Ví dụ thực tế
Ví dụ 1: Tổ chức kiểm thử API thương mại điện tử
// Bộ kiểm thử sơ bộ - Chạy trên mỗi lần commit
describe('[Smoke] Critical API Endpoints', () => {
test('TC_SMOKE_001: API health check returns 200', async () => {
const response = await fetch('https://api.shop.com/health');
expect(response.status).toBe(200);
});
test('TC_SMOKE_002: Database connection is active', async () => {
const response = await fetch('https://api.shop.com/db-status');
expect(response.json()).toHaveProperty('connected', true);
});
});
// Bộ kiểm thử xác thực
describe('[Integration] Authentication Module', () => {
describe('User Registration', () => {
test('TC_AUTH_001: Register with valid email and password', async () => {
// Triển khai kiểm thử
});
test('TC_AUTH_002: Reject registration with duplicate email', async () => {
// Triển khai kiểm thử
});
test('TC_AUTH_003: Reject weak passwords', async () => {
// Triển khai kiểm thử
});
});
describe('User Login', () => {
test('TC_AUTH_004: Login with valid credentials', async () => {
// Triển khai kiểm thử
});
test('TC_AUTH_005: Reject invalid password', async () => {
// Triển khai kiểm thử
});
});
});
// Bộ kiểm thử quản lý sản phẩm
describe('[Integration] Product Management', () => {
test('TC_PROD_001: Get product list', async () => {
// Triển khai kiểm thử
});
test('TC_PROD_002: Get product by ID', async () => {
// Triển khai kiểm thử
});
test('TC_PROD_003: Search products by name', async () => {
// Triển khai kiểm thử
});
test('TC_PROD_004: Filter products by category', async () => {
// Triển khai kiểm thử
});
});
// Bộ kiểm thử xử lý đơn hàng
describe('[Integration] Order Processing', () => {
test('TC_ORDER_001: Create order with valid items', async () => {
// Triển khai kiểm thử
});
test('TC_ORDER_002: Calculate correct order total', async () => {
// Triển khai kiểm thử
});
test('TC_ORDER_003: Apply discount code', async () => {
// Triển khai kiểm thử
});
test('TC_ORDER_004: Process payment', async () => {
// Triển khai kiểm thử
});
});
Ví dụ 2: Cấu trúc bộ kiểm thử Apidog
Trong Apidog, bạn tổ chức các bài kiểm thử một cách trực quan:
📁 Kiểm thử API Thương mại điện tử
📁 Kiểm thử sơ bộ (Bộ kiểm thử)
✓ Kiểm tra trạng thái API (Trường hợp kiểm thử)
✓ Trạng thái cơ sở dữ liệu (Trường hợp kiểm thử)
📁 Xác thực (Bộ kiểm thử)
📁 Đăng ký (Bộ kiểm thử con)
✓ Đăng ký hợp lệ (Trường hợp kiểm thử)
✓ Email trùng lặp (Trường hợp kiểm thử)
✓ Mật khẩu yếu (Trường hợp kiểm thử)
📁 Đăng nhập (Bộ kiểm thử con)
✓ Đăng nhập hợp lệ (Trường hợp kiểm thử)
✓ Mật khẩu không hợp lệ (Trường hợp kiểm thử)
📁 Sản phẩm (Bộ kiểm thử)
✓ Liệt kê sản phẩm (Trường hợp kiểm thử)
✓ Lấy chi tiết sản phẩm (Trường hợp kiểm thử)
✓ Tìm kiếm sản phẩm (Trường hợp kiểm thử)
📁 Đơn hàng (Bộ kiểm thử)
✓ Tạo đơn hàng (Trường hợp kiểm thử)
✓ Tính tổng (Trường hợp kiểm thử)
✓ Áp dụng giảm giá (Trường hợp kiểm thử)
Mỗi trường hợp kiểm thử trong Apidog bao gồm:
- Cấu hình yêu cầu (URL, phương thức, tiêu đề, nội dung)
- Các script trước yêu cầu (thiết lập)
- Các khẳng định (xác thực)
- Các script sau phản hồi (dọn dẹp)
Bạn có thể chạy các trường hợp kiểm thử riêng lẻ, toàn bộ bộ kiểm thử hoặc tạo các lần chạy kiểm thử tùy chỉnh kết hợp các trường hợp từ nhiều bộ kiểm thử.
Kết luận
Các trường hợp kiểm thử và bộ kiểm thử phục vụ các mục đích khác nhau nhưng bổ trợ cho nhau trong kiểm thử API. Các trường hợp kiểm thử xác minh các hành vi riêng lẻ với đầu vào và đầu ra mong đợi cụ thể. Các bộ kiểm thử tổ chức các trường hợp kiểm thử liên quan thành các nhóm logic để thực hiện và bảo trì hiệu quả.
Những điểm chính cần nhớ:
- Trường hợp kiểm thử là các bài kiểm thử nguyên tử cho các kịch bản đơn lẻ
- Bộ kiểm thử là tập hợp các trường hợp kiểm thử liên quan
- Sử dụng các trường hợp kiểm thử để xác minh các yêu cầu cụ thể
- Sử dụng các bộ kiểm thử để tổ chức và thực hiện các nhóm kiểm thử
- Giữ các trường hợp kiểm thử độc lập và tập trung
- Tổ chức các bộ kiểm thử theo tính năng, mức độ ưu tiên hoặc loại kiểm thử
- Đặt tên cả hai rõ ràng và mô tả
- Sử dụng các công cụ như Apidog để quản lý các hệ thống phân cấp kiểm thử phức tạp một cách trực quan
Bắt đầu bằng cách viết các trường hợp kiểm thử tập trung cho từng điểm cuối API. Khi bộ sưu tập kiểm thử của bạn phát triển, hãy nhóm các trường hợp liên quan vào các bộ kiểm thử. Sử dụng các thẻ và quy ước đặt tên để làm cho các bài kiểm thử dễ tìm và chạy. Cho dù bạn viết bài kiểm thử bằng mã hay sử dụng công cụ như Apidog, các nguyên tắc vẫn giữ nguyên: các trường hợp kiểm thử nguyên tử, các bộ kiểm thử logic, tổ chức rõ ràng.
Bạn đã sẵn sàng tổ chức các bài kiểm thử API của mình chưa? Hãy thử quản lý bộ kiểm thử trực quan của Apidog - tạo, tổ chức và chạy các trường hợp kiểm thử mà không cần viết mã. Giảm thời gian thiết lập kiểm thử của bạn 60% và chạy bộ kiểm thử đầu tiên của bạn trong vòng chưa đầy 5 phút.
Câu hỏi thường gặp
Sự khác biệt chính giữa một trường hợp kiểm thử và một bộ kiểm thử là gì?
Một trường hợp kiểm thử là một bài kiểm thử đơn lẻ xác minh một hành vi hoặc yêu cầu cụ thể. Một bộ kiểm thử là một tập hợp nhiều trường hợp kiểm thử liên quan được nhóm lại với nhau để thực hiện có tổ chức. Hãy nghĩ các trường hợp kiểm thử như những câu hỏi riêng lẻ và các bộ kiểm thử như bài kiểm tra chứa những câu hỏi đó.
Một trường hợp kiểm thử có thể thuộc nhiều bộ kiểm thử không?
Có. Một trường hợp kiểm thử đơn lẻ có thể được bao gồm trong nhiều bộ kiểm thử. Ví dụ, một trường hợp kiểm thử đăng nhập quan trọng có thể xuất hiện trong cả bộ "Kiểm thử sơ bộ" và bộ "Kiểm thử xác thực" của bạn. Khả năng tái sử dụng này giúp bạn chạy các tổ hợp kiểm thử khác nhau cho các mục đích khác nhau.
Một bộ kiểm thử nên có bao nhiêu trường hợp kiểm thử?
Không có quy tắc cứng nhắc nào, nhưng 5-15 trường hợp kiểm thử cho mỗi bộ là một phạm vi tốt. Nếu bạn có hơn 20 trường hợp kiểm thử trong một bộ, hãy cân nhắc chia nó thành các bộ nhỏ hơn, tập trung hơn. Nếu bạn có ít hơn 5, bạn có thể không cần một bộ kiểm thử nào cả.
Tôi nên viết các trường hợp kiểm thử hay bộ kiểm thử trước?
Hãy viết các trường hợp kiểm thử trước. Bắt đầu bằng cách tạo các bài kiểm thử riêng lẻ cho các hành vi cụ thể. Khi bạn có một số trường hợp kiểm thử liên quan, hãy nhóm chúng vào các bộ kiểm thử. Cách tiếp cận từ dưới lên này đảm bảo các trường hợp kiểm thử của bạn tập trung và các bộ kiểm thử của bạn được tổ chức một cách hợp lý.
Sự khác biệt giữa một bộ kiểm thử và một kịch bản kiểm thử là gì?
Một kịch bản kiểm thử (test scenario) là một mô tả cấp cao về những gì cần kiểm thử (ví dụ: "Luồng đăng nhập người dùng"). Một bộ kiểm thử là tập hợp thực tế các trường hợp kiểm thử có thể thực thi. Một kịch bản kiểm thử có thể trở thành một bộ kiểm thử chứa nhiều trường hợp kiểm thử xác minh các khía cạnh khác nhau của kịch bản đó.
Làm thế nào để tôi tổ chức các bộ kiểm thử cho các API lớn?
Sử dụng cấu trúc phân cấp: tổ chức theo tính năng hoặc mô-đun ở cấp cao nhất, sau đó theo chức năng, sau đó theo loại kiểm thử. Ví dụ: "Quản lý người dùng" (mô-đun) → "Xác thực" (chức năng) → "Kiểm thử đăng nhập" (bộ kiểm thử) → các trường hợp kiểm thử riêng lẻ. Giữ việc lồng nhau tối đa 2-3 cấp độ.
Các bộ kiểm thử có thể chứa các bộ kiểm thử khác không?
Có. Các bộ kiểm thử có thể được lồng vào nhau để tạo hệ thống phân cấp. Ví dụ, một bộ "Kiểm thử API" có thể chứa các bộ con "Kiểm thử xác thực" và "Kiểm thử quản lý người dùng". Tuy nhiên, tránh lồng ghép quá mức (hơn 3 cấp độ) vì điều đó khiến việc điều hướng và duy trì kiểm thử trở nên khó khăn hơn.
Những công cụ nào giúp quản lý các trường hợp kiểm thử và bộ kiểm thử?
Các công cụ phổ biến bao gồm Jest và Mocha cho JavaScript, Pytest cho Python, JUnit cho Java và Postman cho kiểm thử API. Apidog cung cấp quản lý bộ kiểm thử trực quan mà không cần viết mã, giúp dễ dàng tổ chức và thực hiện các trường hợp kiểm thử API thông qua giao diện GUI.
