Họ đang đo gì
Bạn có phân biệt được chỉ số với mục tiêu không. Đây là ví dụ sách giáo khoa của định luật Goodhart.
Trả lời ngắn~30 giây
Nó nói 90% dòng được thực thi trong lúc chạy test — không nói rằng có assertion nào kiểm chứng kết quả. Một bộ test gọi mọi hàm và không assert gì vẫn cho độ phủ 100%. Mình dùng độ phủ theo chiều ngược lại: nhìn phần CHƯA phủ để tìm nhánh bị bỏ quên, chứ không đặt một con số làm mục tiêu.
Giải thích sâu
Có nhiều loại độ phủ và chúng nói những điều khác nhau. Phủ dòng dễ đạt nhất và yếu nhất. Phủ nhánh mạnh hơn: nó đòi cả nhánh if lẫn nhánh ngầm else, mà nhánh else bị bỏ quên chính là nơi bug hay nằm. Phủ điều kiện đi xa hơn nữa, yêu cầu mỗi điều kiện con trong một biểu thức phức hợp được cả hai giá trị. Nói được sự khác biệt này cho thấy bạn hiểu chỉ số chứ không chỉ đọc con số.
Đặt ngưỡng bắt buộc trong CI có tác dụng phụ dự đoán được: người ta viết test cho những phần dễ phủ nhất — getter, DTO, mã sinh tự động — vì đó là cách rẻ nhất để đẩy con số lên. Trong khi phần khó phủ (xử lý lỗi, đường bất thường) chính là phần cần test nhất và bị bỏ lại. Nghĩa là ngưỡng bắt buộc có thể làm bộ test tệ đi trong khi con số đẹp lên.
Thứ mình quan tâm hơn độ phủ là mutation testing: công cụ sửa nhỏ code của bạn (đảo một dấu so sánh, đổi hằng số) rồi xem có test nào đỏ lên không. Nếu code bị hỏng mà test vẫn xanh thì test đó không kiểm chứng gì. Nó chậm hơn nhiều nên thường chạy theo lịch chứ không chặn PR, nhưng nó trả lời đúng câu hỏi mà độ phủ không trả lời được.
Câu hỏi tiếp theo họ sẽ hỏi
?Vậy độ phủ bao nhiêu là hợp lý?
Mình không đặt con số cho cả dự án mà đặt theo vùng: logic nghiệp vụ và tính tiền thì gần như phải phủ hết, còn tầng ghép nối và cấu hình thì thấp cũng không sao. Một con số chung cho toàn repo luôn vừa quá nghiêm với chỗ này vừa quá lỏng với chỗ kia.
Trả lời thế này là mất điểm
- Coi 100% là mục tiêu. Nó khuyến khích test những thứ không đáng test và vẫn không nói gì về chất lượng assertion.