1. Tóm tắt nhanh & bối cảnh: module tính cước viễn thông
Bạn là tester trong đội billing của một nhà mạng. Module tinhCuocGoi() tính tiền cuộc gọi/data hàng tháng cho hàng triệu thuê bao — sai một dòng logic, hàng nghìn khách hàng có thể bị tính dư hoặc tính thiếu tiền. Mỗi lần dev build xong, CI/CD tự sinh báo cáo coverage (kiểu Jacoco, Istanbul, SonarQube) và gắn link vào pull request. Bạn không cần tự viết công cụ đo coverage, nhưng bạn CẦN đọc đúng báo cáo đó: biết phân biệt statement, branch, condition; biết chỉ số nào đáng tin, chỉ số nào dễ gây ảo tưởng an toàn; và biết khi nào phải bổ sung ca kiểm thử thủ công nhắm đúng vào lỗ hổng thay vì tin tưởng mù quáng vào con số phần trăm.
function tinhCuocGoi(soPhut, goiCuoc, laKhachVIP, ngayTrongThang) {
let cuoc = 0; // DEFINE #1
if (soPhut <= goiCuoc.phutMienPhi) {
cuoc = 0; // nhanh THEN - trong goi, khong tinh tien
} else {
cuoc = (soPhut - goiCuoc.phutMienPhi) * goiCuoc.donGia; // DEFINE #2 (nhanh ELSE)
}
if (laKhachVIP && ngayTrongThang >= 25) { // dieu kien kep (compound condition)
cuoc = cuoc * 0.8; // USE cuoc + DEFINE #3 - giam gia cuoi thang
}
return cuoc; // USE cuoi cung (DU-path ket thuc)
}2. Statement coverage — dòng lệnh nào đã chạy, dòng nào chưa
Statement coverage là mức đơn giản nhất: một dòng lệnh được tính là 'đã phủ' nếu nó được thực thi ít nhất một lần trong toàn bộ bộ kiểm thử, bất kể giá trị đầu vào là gì. Với hàm tinhCuocGoi(), chỉ cần một ca gọi trong gói (soPhut nhỏ hơn phutMienPhi) và một ca gọi vượt gói là đủ để mọi DÒNG lệnh — kể cả dòng gán 'cuoc' ở cả hai nhánh if — đều được chạm tới ít nhất một lần. Báo cáo coverage tool thường tô xanh các dòng đã chạy, tô đỏ các dòng chưa từng chạy, giúp tester nhìn nhanh 'code chết' hoặc phần logic hoàn toàn chưa được thử.
Điểm mạnh của statement coverage là đơn giản, dễ hiểu, dễ báo cáo cho quản lý. Nhưng điểm yếu chí mạng: nó KHÔNG phân biệt các trường hợp bên trong cùng một điều kiện. Dòng if(soPhut <= goiCuoc.phutMienPhi) chỉ cần chạy MỘT lần, dù nhánh true hay nhánh false, là được tính 'đã phủ' — dòng if đó không đòi hỏi cả hai khả năng đều được thử. Đây chính là lý do một module đạt 96% statement coverage (như trong dashboard ở chương 9) vẫn có thể ẩn giấu một nhánh nghiệp vụ quan trọng chưa từng chạy, như nhánh giảm giá cuối tháng cho khách VIP.
3. Branch/Decision coverage — nhánh rẽ nào đã được đi qua
Branch coverage (còn gọi decision coverage) khắt khe hơn statement coverage một bậc: mỗi ĐIỂM RẼ NHÁNH (if, else, switch-case, vòng lặp có điều kiện...) phải được đi qua ở CẢ HAI khả năng — đúng và sai — chứ không chỉ một trong hai. Với if(soPhut <= goiCuoc.phutMienPhi), branch coverage đòi hỏi ít nhất một ca cho nhánh true (gọi trong gói) VÀ ít nhất một ca cho nhánh false (gọi vượt gói). Với if(laKhachVIP && ngayTrongThang >= 25), branch coverage đòi hỏi cả nhánh true (được giảm giá) và nhánh false (không được giảm giá) đều từng chạy — đây chính là nhánh dễ bị bỏ sót nhất trong thực tế vì nó chỉ đúng vào cuối tháng, một khung thời gian hẹp mà đội test hay quên chủ động mô phỏng.
4. Condition coverage — điều kiện kép & bẫy short-circuit
Khi một điều kiện là biểu thức KÉP như laKhachVIP && ngayTrongThang >= 25, branch coverage chỉ quan tâm KẾT QUẢ CHUNG của cả biểu thức (true hoặc false), không quan tâm từng vế riêng lẻ. Condition coverage đi sâu hơn: mỗi ĐIỀU KIỆN CON (ở đây là laKhachVIP và ngayTrongThang >= 25) phải nhận CẢ true lẫn false ở các ca test khác nhau, độc lập với kết quả chung. Điều này quan trọng vì hai ca test có thể khiến biểu thức tổng đủ true/false (branch coverage 100%) nhưng một điều kiện con cụ thể vẫn chưa bao giờ được thử theo cả hai hướng — như bạn sẽ thấy rõ trong tình huống 2 ở chương 8.
Có một bẫy riêng cần tester nhớ: hầu hết ngôn ngữ lập trình (JavaScript, Java, Python...) dùng SHORT-CIRCUIT EVALUATION cho toán tử &&. Nghĩa là nếu vế trái (laKhachVIP) đã là false, ngôn ngữ sẽ KHÔNG BAO GIỜ đánh giá vế phải (ngayTrongThang >= 25) nữa — vế phải bị 'bỏ qua' hoàn toàn về mặt thực thi. Vì vậy một ca test với laKhachVIP=false không hề cung cấp bất kỳ thông tin gì về việc điều kiện ngày tháng hoạt động đúng hay sai; muốn thực sự thử vế phải, bắt buộc phải có ca với laKhachVIP=true. Hiểu rõ short-circuit giúp tester không nhầm lẫn 'đã chạy qua dòng' với 'đã thực sự đánh giá điều kiện'.
💬 Bình luận (0)
Chưa có bình luận nào. Hãy là người đầu tiên!