Coverage trả lời được dòng nào chưa từng chạy, nhưng không trả lời được hành vi nào chưa được kiểm chứng. Đó là lý do nó là chỉ báo tốt khi thấp và là chỉ báo vô nghĩa khi cao.
Test sau đây đạt 100% line coverage cho calculateDiscount mà không kiểm chứng gì:
it('runs', () => {
calculateDiscount(order) // no assertion at all
})Vì sao 100% không nên là mục tiêu:
- Chạy qua một dòng khác với kiểm tra dòng đó đúng. Coverage đếm cái thứ nhất.
- Ép 100% khiến người ta viết test cho getter, cho nhánh
catchkhông thể xảy ra, hoặc thêm assert giả để qua ngưỡng. Chi phí bảo trì tăng, giá trị bằng không. - Phần khó test nhất (concurrency, timeout, lỗi mạng) thường vẫn nằm ngoài, dù con số đã 95%.
Dùng coverage cho đúng: đọc báo cáo, không đọc con số. Mở phần chưa phủ và hỏi "chỗ này sai thì có ai mất gì không". Nếu có thì viết test, không thì bỏ qua. Nếu buộc phải đặt ngưỡng trong CI thì đặt để chặn tụt lùi (không thấp hơn hiện tại) chứ đừng đặt một con số tròn để cả nhóm chạy theo.
Khi thật sự cần đánh giá chất lượng bộ test, mutation testing (cố ý làm hỏng code xem test có bắt được không) cho tín hiệu tốt hơn coverage nhiều.