Pipeline CI/CD của tôi đã vượt qua trong suốt 3 tháng — Cho đến khi tôi đọc nhật ký (logs)
Những dấu tích xanh thật dễ chịu. Mọi pull request đều vượt qua. Mọi đợt deploy đều thành công.
Thế rồi một người dùng báo cáo một tính năng bị lỗi. Nó đã bị lỗi trong nhiều tuần liền.
Tôi mở nhật ký pipeline lên. Những bản build "vượt qua" đã lừa dối chúng tôi.
Quy trình của chúng tôi trông có vẻ hoàn hảo:
- Linting
- Unit tests
- Integration tests
- Build
- Deploy
Mọi bước đều có tỷ lệ thành công 100% trong suốt nhiều tháng.
Nút export không có phản ứng gì khi được nhấn. Không có lỗi nào xuất hiện. Tôi đã truy vết ngược lại một thay đổi từ 11 tuần trước. Pipeline đã vượt qua. Code review đã được phê duyệt. Tính năng đó đã bị lỗi ngay từ đầu.
Vấn đề không nằm ở mã nguồn của chúng tôi. Nó nằm ở mã kiểm thử (test code).
Các bài integration tests của chúng tôi đã sử dụng mock cho mọi thứ. Chúng tôi đã mock toàn bộ dịch vụ export. Bài kiểm thử chỉ kiểm tra cái mock thay vì kiểm tra mã nguồn thực tế. Cái mock đó luôn trả về trạng thái thành công.
Chúng tôi đã rơi vào cái bẫy lạm dụng mock (over-mocking):
- Unit tests: Mock mọi thứ để cô lập đơn vị. Điều này thì ổn.
- Integration tests: Mock mọi thứ để tăng tốc độ. Đây là một sai lầm.
- E2E tests: Đã bỏ lỡ luồng cụ thể này.
Các bài integration tests của chúng tôi thực chất chỉ là những unit tests tốn kém. Chúng xác nhận rằng các mock hoạt động tốt. Chúng không xác nhận rằng mã nguồn của chúng tôi hoạt động tốt.
Tôi đã thực hiện ba thay đổi để khắc phục điều này:
Giới hạn mock trong unit tests. Integration tests phải tác động đến cơ sở dữ liệu, API và hệ thống tệp thực tế. Nếu một bài kiểm thử chạy chậm, đừng che giấu nó bằng một cái mock. Hãy dùng chính tốc độ đó như một tín hiệu để tối ưu hóa.
Thêm contract tests. Những bài kiểm thử này đảm bảo rằng các mock của bạn khớp với hành vi thực tế của dịch vụ. Nếu một mock trả về dữ liệu mà dịch vụ thực tế không trả về, contract test sẽ thất bại.
Theo dõi độ bao phủ (coverage) thực tế. Chúng tôi ngừng nhìn vào tỷ lệ vượt qua đơn thuần. Chúng tôi nhìn vào những gì các bài kiểm thử thực sự thực thi. Chỉ số coverage của chúng tôi đã giảm từ 94% xuống còn 67%. Đây là chỉ số trung thực nhất mà chúng tôi có.
Một pipeline "xanh" không có nghĩa là mã của bạn hoạt động. Nó chỉ có nghĩa là các bài kiểm thử của bạn đã vượt qua. Đây là hai việc hoàn toàn khác nhau.
Những lỗi nguy hiểm nhất là những lỗi mà pipeline báo rằng mọi thứ vẫn ổn.
Hãy tự hỏi bản thân những câu hỏi sau:
- Các bài kiểm thử của tôi đang bắt lỗi hay chỉ đang xác nhận các mock?
- Các bài integration tests của tôi có thực sự là "tích hợp" không?
- Nếu tôi loại bỏ tất cả các mock, có bao nhiêu bài kiểm thử vẫn vượt qua?
- Tôi đang đo lường độ bao phủ (coverage) hay sự tin cậy (confidence)?
Một pipeline không bao giờ thất bại thì không đáng tin cậy. Nó đơn giản là chưa được kiểm thử.
Source: https://dev.to/kollittle/my-cicd-pipeline-passed-for-3-months-then-i-read-the-logs-4mbj
