Phần lớn lỗi mà người dùng gặp ở một ứng dụng web không nằm trong một hàm tính toán, mà nằm ở chỗ các mảnh ghép nối với nhau: điểm cuối API trả sai mã trạng thái, quên kiểm quyền, đọc nhầm dữ liệu của khách khác. Kiểm thử đơn vị không thấy những lỗi này. Kiểm thử tích hợp gọi API như một ứng dụng thật sẽ gọi, rồi kiểm phản hồi, mới bắt được.
Trợ lý AI viết kiểm thử tích hợp khá nhanh nếu bạn đưa đặc tả rõ, và đặc biệt hữu ích ở phần liệt kê ca: đường đúng, đầu vào sai, chưa đăng nhập, sai quyền, không tìm thấy, trùng lặp. Bài này đi qua những gì cần kiểm ở mỗi điểm cuối, cách giao việc cho AI, một ví dụ giả định bằng pytest, và hai chỗ hay làm hỏng kiểm thử tích hợp: dịch vụ ngoài và cơ sở dữ liệu.
Vì sao kiểm thử đơn vị không đủ cho API
Một điểm cuối API là hợp đồng giữa máy chủ và mọi ứng dụng gọi nó: ứng dụng di động, trang web, đối tác. Hợp đồng đó gồm đường dẫn, phương thức, dữ liệu gửi lên, mã trạng thái trả về, định dạng thông báo lỗi, và quan trọng nhất là ai được làm gì. Kiểm thử đơn vị kiểm từng hàm bên trong, nhưng không kiểm được hợp đồng đó có được giữ khi mọi thứ ghép lại hay không.
Mã AI viết cho tầng API có vài kiểu lỗi lặp lại. Trả 200 kèm thông báo lỗi trong thân phản hồi thay vì mã lỗi đúng. Bắt mọi ngoại lệ rồi trả 500 chung chung, làm ứng dụng phía trước không phân biệt được lỗi do người dùng nhập sai hay do máy chủ hỏng. Và nguy hiểm nhất: lấy bản ghi theo mã số trong đường dẫn mà không kiểm bản ghi đó có thuộc về người đang đăng nhập hay không.
Kiểm thử tích hợp chạy chậm hơn kiểm thử đơn vị, nên không cần kiểm lại mọi ca logic. Phân công hợp lý là: logic tính toán kiểm ở tầng đơn vị, còn tầng tích hợp tập trung vào hợp đồng, phân quyền và cách các thành phần nói chuyện với nhau.
Kiểm gì ở mỗi điểm cuối
Bảng này là khung để bạn đưa vào câu lệnh hoặc tự soát. Mã trạng thái là theo quy ước phổ biến; dự án của bạn có thể quy ước khác, miễn là nhất quán và được ghi trong đặc tả.
| Nhóm ca | Ví dụ | Kết quả mong đợi thường gặp |
|---|---|---|
| Đường đúng | Tạo đơn hợp lệ, xem đơn của chính mình | 200 hoặc 201, thân phản hồi đúng cấu trúc |
| Chưa xác thực | Gọi không kèm mã đăng nhập, mã hết hạn | 401 |
| Sai quyền | Khách thường gọi chức năng quản trị, xem đơn của khách khác | 403, hoặc 404 nếu không muốn lộ là bản ghi tồn tại |
| Đầu vào sai | Thiếu trường bắt buộc, sai kiểu, số âm, chuỗi quá dài | 400 hoặc 422, thông báo chỉ rõ trường nào sai |
| Không tìm thấy | Mã số không tồn tại | 404 |
| Xung đột | Tạo trùng, sửa bản ghi đã bị người khác sửa | 409 |
| Phân trang và giới hạn | Trang vượt quá, kích thước trang quá lớn | Danh sách rỗng hoặc lỗi rõ ràng, không trả toàn bộ bảng |
Dòng cuối hay bị bỏ qua: một điểm cuối danh sách không giới hạn kích thước trang là điểm cuối có thể làm sập máy chủ khi dữ liệu lớn lên. Ca kiểm thử với kích thước trang rất lớn nên khẳng định máy chủ tự giới hạn.
Giao việc cho AI: đặc tả trước, mã sau
Nếu dự án có tài liệu mô tả API theo chuẩn như OpenAPI, đó là đầu vào tốt nhất cho AI: nó chứa đường dẫn, kiểu dữ liệu, mã trạng thái mong đợi. Nếu không có, viết một đoạn mô tả ngắn cho từng điểm cuối. Câu lệnh mẫu:
"Viết kiểm thử tích hợp bằng pytest cho điểm cuối tạo đơn hàng và xem đơn hàng theo mô tả dưới đây. Dùng ứng dụng thử nghiệm của khung web, không gọi máy chủ thật. Có hai tài khoản thử là khách A và khách B, khai báo sẵn trong tệp cấu hình kiểm thử. Với mỗi điểm cuối, viết ca cho: đường đúng, chưa đăng nhập, khách B xem đơn của khách A, thiếu trường bắt buộc, mã số không tồn tại. Kiểm cả mã trạng thái lẫn các trường chính của thân phản hồi. Trước khi viết, liệt kê các ca và mã trạng thái mong đợi để xác nhận."
Đừng dán khoá API, mã đăng nhập thật hay địa chỉ máy chủ nội bộ vào câu lệnh. Tài khoản thử, khoá thử và địa chỉ thử khai báo trong tệp cấu hình kiểm thử, lấy từ biến môi trường, và AI chỉ cần biết tên biến. Nếu bạn dán phản hồi thật từ máy chủ để làm ví dụ, che dữ liệu khách trong đó trước.
Ví dụ giả định với pytest
Giả sử ứng dụng viết bằng một khung web Python có sẵn bộ khách thử nghiệm, mã đăng nhập thử của hai khách được khai báo trong tệp cấu hình kiểm thử. Hai ca tiêu biểu:
from fastapi.testclient import TestClient
from ung_dung import app
khach = TestClient(app)
KHACH_A = {"Authorization": "Bearer ma-thu-khach-a"}
KHACH_B = {"Authorization": "Bearer ma-thu-khach-b"}
def test_tao_don_thieu_san_pham_bi_tu_choi():
r = khach.post("/don-hang", json={"so_luong": 2}, headers=KHACH_A)
assert r.status_code == 422
def test_khach_b_khong_xem_duoc_don_cua_khach_a(don_cua_khach_a):
r = khach.get(f"/don-hang/{don_cua_khach_a}", headers=KHACH_B)
assert r.status_code in (403, 404)
Ca thứ hai dùng một fixture tạo sẵn đơn của khách A và trả về mã số đơn. Đây là ca đáng giá nhất của cả bộ: nó bắt đúng lỗi lấy bản ghi theo mã số mà quên kiểm chủ sở hữu. Nếu dự án quyết định trả 404 để không lộ đơn có tồn tại, sửa câu kiểm cho chặt về đúng một mã. Cú pháp bộ khách thử nghiệm khác nhau giữa các khung web và phiên bản; đối chiếu tài liệu của khung bạn dùng.
Ca thứ nhất nhìn thì đơn giản nhưng giữ một phần hợp đồng quan trọng: đầu vào thiếu trường phải bị từ chối bằng mã lỗi phía người dùng, không phải lỗi máy chủ. Nếu bạn muốn chặt hơn, khẳng định thêm thân phản hồi có nêu tên trường bị thiếu, để ứng dụng phía trước hiển thị được thông báo đúng chỗ cho người dùng.
Kiểm phân quyền và tách dữ liệu: phần không được bỏ
Mỗi điểm cuối đọc theo mã số có một ca người khác truy cập. Xem, sửa, xoá, tải tệp đính kèm, xuất báo cáo. AI hay viết đúng phần lọc ở danh sách nhưng quên ở điểm cuối xem chi tiết hoặc tải tệp. Với hệ thống nhiều khách hàng dùng chung một cơ sở dữ liệu, đây là lỗi làm rò dữ liệu sang khách khác.
Mỗi chức năng quản trị có một ca tài khoản thường gọi vào. Kiểm cả trường hợp ẩn nút trên giao diện nhưng điểm cuối vẫn mở. Giao diện không phải lớp bảo vệ.
Sửa dữ liệu không cho đổi trường chủ sở hữu. Gửi lên thân yêu cầu có thêm trường chủ sở hữu hoặc vai trò; kiểm rằng máy chủ bỏ qua hoặc từ chối, không âm thầm nhận.
Danh sách chỉ trả dữ liệu của người gọi. Tạo dữ liệu cho cả hai khách, gọi danh sách bằng khách A, khẳng định không có bản ghi nào của khách B. Ca này rẻ mà bắt được truy vấn quên điều kiện lọc.
Thêm ca mỗi khi có điểm cuối mới. Nhóm phân quyền dễ bị quên nhất khi tính năng mới được thêm vội. Ghi vào tệp hướng dẫn cho AI rằng mọi điểm cuối mới phải có ca người khác truy cập, và người rà kiểm điều này trước tiên.
Dịch vụ ngoài: giả lập hay gọi thật
Ứng dụng thật gọi cổng thanh toán, dịch vụ gửi thư, dịch vụ bản đồ, mô hình AI. Trong kiểm thử tích hợp, có vài lựa chọn:
- Giả lập ở ranh giới HTTP. Chặn lời gọi ra ngoài và trả phản hồi mẫu. Nhanh, ổn định, nhưng chỉ đúng khi phản hồi mẫu giống phản hồi thật. Lấy mẫu từ tài liệu chính thức hoặc từ môi trường thử của nhà cung cấp, đã che dữ liệu.
- Môi trường thử của nhà cung cấp. Nhiều dịch vụ thanh toán và gửi thư có chế độ thử không làm phát sinh giao dịch thật. Dùng cho một số ít kiểm thử chạy định kỳ, không chạy ở mọi lần đẩy mã.
- Ghi lại rồi phát lại. Ghi phản hồi thật một lần, lưu vào kho, các lần sau phát lại. Nhớ che khoá và dữ liệu cá nhân trong bản ghi trước khi lưu.
- Ca lỗi của dịch vụ ngoài. Dịch vụ chậm, trả lỗi, trả dữ liệu lạ. Đây là chỗ giả lập phát huy giá trị nhất, vì không thể bắt dịch vụ thật hỏng theo ý mình.
- Không bao giờ gọi dịch vụ thật bằng khoá thật từ kiểm thử tự động. Một vòng lặp lỗi có thể gửi hàng nghìn thư hoặc tạo giao dịch thật.
Khi nhờ AI viết đồ giả cho dịch vụ ngoài, kiểm cấu trúc phản hồi nó bịa với tài liệu thật của dịch vụ. AI hay đoán tên trường theo cảm tính, và đồ giả sai cấu trúc làm kiểm thử xanh trong khi mã thật sẽ hỏng.
Cơ sở dữ liệu trong kiểm thử tích hợp
Phần lớn kiểm thử tích hợp chạm vào cơ sở dữ liệu. Làm sai chỗ này, kiểm thử hoặc chậm, hoặc chập chờn, hoặc xanh giả. Trình tự nên theo:
- Dùng cùng loại cơ sở dữ liệu với môi trường thật, chạy trong vùng chứa (container) riêng cho kiểm thử. Thay bằng loại nhẹ hơn cho nhanh thì khác biệt về cú pháp, kiểu dữ liệu, cách sắp xếp chữ có dấu sẽ bị che.
- Chạy toàn bộ kịch bản chuyển đổi cấu trúc (migration) trước khi kiểm thử, để bảng giống hệt môi trường thật. Đây cũng là cách kiểm luôn kịch bản chuyển đổi.
- Mỗi ca chạy trong một giao dịch rồi huỷ ở cuối, hoặc tự dọn dữ liệu nó tạo ra. Không ca nào dựa vào dữ liệu ca khác để lại.
- Dữ liệu ban đầu tạo bằng hàm sinh có seed cố định, không sao chép từ hệ thống thật.
- Kịch bản kiểm thử kiểm biến môi trường và từ chối chạy nếu chuỗi kết nối trỏ vào cơ sở dữ liệu sản phẩm.
Bước cuối nghe thừa cho tới khi có người chạy nhầm. Một kiểm thử tích hợp có bước dọn dữ liệu chạy trên cơ sở dữ liệu thật là sự cố nghiêm trọng, và chỉ cần một dòng kiểm ở đầu là chặn được.
Câu hỏi thường gặp
Kiểm thử tích hợp có nên chạy ở mọi lần đẩy mã không?
Phần nhanh và quan trọng thì nên, nhất là ca phân quyền. Phần chậm hoặc gọi môi trường thử của nhà cung cấp có thể chạy theo lịch hoặc trước khi phát hành. Mục tiêu là phần chặn gộp mã chạy xong trong vài phút.
Trả 403 hay 404 khi người dùng xem dữ liệu không phải của mình?
Cả hai đều phổ biến. 404 giấu luôn việc bản ghi có tồn tại, phù hợp khi mã số dễ đoán. 403 rõ ràng hơn cho ứng dụng phía trước. Quan trọng là nhóm chọn một cách, ghi vào đặc tả, và kiểm thử khẳng định đúng mã đó.
AI có tự viết được kiểm thử từ tài liệu OpenAPI không?
Viết được bộ khung khá nhanh: mỗi đường dẫn, mỗi phương thức, các mã trạng thái đã khai. Nhưng tài liệu thường không nói về phân quyền và quy tắc nghiệp vụ, nên phần ca quan trọng nhất vẫn cần bạn bổ sung và duyệt.
Có nên dùng cơ sở dữ liệu trong bộ nhớ cho nhanh không?
Chỉ khi ứng dụng thật cũng dùng đúng loại đó. Nếu không, khác biệt về cú pháp, kiểu dữ liệu và cách so sánh chuỗi có dấu sẽ làm kiểm thử xanh mà máy thật lỗi. Vùng chứa chạy đúng loại cơ sở dữ liệu thường đủ nhanh cho đa số dự án.
Làm sao kiểm điểm cuối có gọi mô hình AI?
Giả lập lời gọi mô hình trong kiểm thử tích hợp để kết quả ổn định và không tốn chi phí. Kiểm phần bạn kiểm soát: xử lý khi mô hình trả lỗi hoặc chậm, khi phản hồi sai định dạng, và việc che dữ liệu trước khi gửi đi. Chất lượng câu trả lời đo bằng cách đánh giá riêng.
Kiểm thử tích hợp có thay được kiểm thử bằng tay trước khi phát hành không?
Thay được phần lặp lại, như kiểm từng điểm cuối và từng quyền. Không thay được việc một người thật dùng thử luồng chính trên thiết bị thật, nơi lộ ra lỗi trải nghiệm mà kiểm thử tự động không nhìn thấy.