Họ đang đo gì
Bạn có nghĩ về chi phí bảo trì test không, hay chỉ nghĩ về việc viết chúng.
Trả lời ngắn~30 giây
Càng lên cao thì test càng chậm, càng dễ rung, và càng đắt để sửa khi hỏng — nên nhiều unit test ở đáy, ít test tích hợp ở giữa, rất ít test đầu-cuối ở đỉnh. Mình đồng ý về mặt chi phí nhưng không đồng ý nếu áp dụng máy móc: giá trị của một test nằm ở việc nó bắt được lỗi thật, và có những hệ thống mà gần như mọi lỗi thật đều nằm ở chỗ các thành phần GẶP nhau — lúc đó tầng tích hợp mới xứng đáng nhận phần lớn công sức.
Giải thích sâu
Cái bẫy của việc theo kim tự tháp quá chặt là bạn có thể đạt độ phủ unit cao mà vẫn hỏng ở production, vì mọi thứ được mock. Test một service với repository đã mock chứng minh rằng service gọi đúng phương thức, chứ không chứng minh truy vấn SQL bên dưới chạy được. Đó là lý do test tích hợp với database thật (bằng Testcontainers hoặc tương đương) thường cho niềm tin trên mỗi giờ công cao hơn nhiều so với thêm unit test.
Một hình dạng thay thế đáng biết là “testing trophy”: ít unit test hơn, nhiều test tích hợp hơn, cộng với kiểm tra kiểu tĩnh làm nền. Lập luận là TypeScript và linter đã bắt được đúng loại lỗi mà nhiều unit test tầm thường đang bắt — hàm nhận sai kiểu, thiếu trường — nên viết lại chúng bằng test là trả tiền hai lần.
Câu hỏi tiếp theo họ sẽ hỏi
?Test đầu-cuối nên phủ cái gì?
Vài luồng quan trọng nhất về mặt kinh doanh — đăng ký, thanh toán — chứ không phải mọi màn hình. Mục tiêu là phát hiện “toàn bộ hệ thống ghép lại vẫn chạy”, và ba đến năm test làm được điều đó; ba mươi test thì bạn dành thời gian sửa test rung thay vì viết tính năng.
Trả lời thế này là mất điểm
- Đặt mục tiêu độ phủ 100%. Nó khuyến khích viết test cho getter và bỏ qua những nhánh khó — đúng những nhánh hay có bug.