Dữ liệu FDE TimesViệc làm FDE đang mở 862▼55 Thay đổi số việc đang mở trong 7 ngày, so sánh cùng phạm vi: không tính việc của các công ty mới được theo dõi tuần nàyMới trong 7 ngày 70Công ty đang tuyển 180Nhận làm từ xa 24%Lương trung vị (Mỹ) $200kTuyển nhiều nhất Palantir 95
中文EN

Tờ báo của nghề Forward Deployed Engineer

Sách & khoá học

Vì sao code tích hợp bạn bàn giao cần ít mock hơn bạn nghĩ

Vladimir Khorikov đưa ra một quy tắc mock rất gọn, kèm theo cái giá mà bộ test nào cũng phải trả.

Chia sẻLinkedInFacebookX

Tóm tắt nhanh

  • Khorikov chỉ cho mock những dependency mà hệ thống khác cũng truy cập được. Database riêng của ứng dụng thì nên test bằng instance thật.
  • Theo một bản tóm tắt sách, test tốt cần chống regression, chịu được refactor, cho phản hồi nhanh và dễ bảo trì. Ba tiêu chí đầu không thể cùng đạt tối đa.
  • Sách dành cho người đã biết unit test cơ bản. Ví dụ viết bằng C# nhưng áp dụng được cho mọi ngôn ngữ.
Sơ đồ service đơn hàng nằm ở giữa. Bên trái là Postgres riêng của service, ghi chú managed, chạy instance thật trong test. Bên phải là ERP, được kế toán và kho của khách cùng đọc, ghi chú unmanaged, chỉ mock ở biên. Một vạch cam đánh dấu ranh giới mock giữa service và ERP.
Theo quy tắc của Vladimir Khorikov, test chạy trên database riêng của service và chỉ mock API mà các hệ thống khác cũng phụ thuộc vào.

Chỉ nên mock những dependency bên ngoài mà các hệ thống khác cũng dùng chung. Vladimir Khorikov, tác giả cuốn Unit Testing: Principles, Practices, and Patterns, viết quy tắc này trên blog Enterprise Craftsmanship năm 2020. Nếu bạn là FDE vừa viết xong một service nối hệ thống của khách với sản phẩm của công ty, câu này có thể thay đổi cả bộ test bạn sắp bàn giao.

Lý do nằm ở hoàn cảnh bàn giao. Khi bạn rời site khách hàng, đội kỹ thuật của khách sẽ là người sửa code tích hợp đó. Bộ test là thứ duy nhất báo cho họ biết họ vừa làm hỏng gì. Bộ test mock tràn lan, cứ refactor là đỏ dù chẳng có bug, sẽ nhanh chóng bị tắt đi. Đến lúc đó thì có test cũng như không.

Mock hay không tùy vào ai dùng chung dependency

Khorikov chia các dependency ngoài tiến trình làm hai loại. Managed dependency là thứ chỉ truy cập được qua ứng dụng của bạn, ví dụ database riêng của service. Unmanaged dependency là thứ mà các ứng dụng khác cũng truy cập được. Từ đó ông rút ra quy tắc: dùng instance thật cho managed, chỉ mock unmanaged.

Thử hình dung một service bạn viết cho một công ty phân phối. Service nhận đơn hàng, lưu vào Postgres riêng, rồi đẩy sang API của hệ thống ERP mà kế toán và kho của khách cùng đọc.

Postgres là managed, vì không ai ngoài service của bạn chạm vào nó. ERP là unmanaged, vì những lời gọi bạn gửi sang đó là hợp đồng mà các hệ thống khác cũng phụ thuộc vào.

Áp quy tắc vào ví dụ này, test sẽ chạy trên Postgres thật và mock ERP ở biên, kiểm tra nội dung request gửi đi có đúng không. Giả sử mấy tháng sau đội của khách đổi tên một cột trong migration.

Nếu bạn đã mock database, test vẫn xanh còn production thì hỏng. Nếu chạy trên Postgres thật, test đỏ ngay trong CI. Ngược lại, mock ERP vẫn hợp lý: test chỉ cần chứng minh service giữ đúng hợp đồng với bên ngoài.

Không bộ test nào được cả ba thứ cùng lúc

Câu hỏi tiếp theo là làm sao chấm một test tốt hay dở. Theo một bản ghi chép tóm tắt sách, Khorikov đưa ra bốn trụ cột: bảo vệ khỏi regression, chịu được refactor, phản hồi nhanh và dễ bảo trì. Điểm mấu chốt là ba trụ cột đầu loại trừ nhau. Bạn chỉ được chọn hai trong ba, giống kiểu đánh đổi của định lý CAP.

Quay lại service đơn hàng. Một test end-to-end gọi vào sandbox ERP thật bắt được nhiều bug và không vỡ khi bạn đổi cấu trúc code bên trong, nhưng nó chậm. Một test nhỏ mock mọi thứ chạy rất nhanh, nhưng bám chặt vào chi tiết cài đặt nên vỡ ngay khi bạn tách một hàm. Kiểu test thứ hai là thứ đội của khách sẽ ghét nhất.

Hiểu được sự đánh đổi này, bạn sẽ không còn tìm một loại test “đúng” duy nhất. Với service đơn hàng, cách chia hợp lý là nhiều test nhanh cho logic nghiệp vụ thuần, cộng một số ít integration test chạy trên database thật.

Trong danh sách nội dung sách, Manning có nêu việc dùng integration test để kiểm tra toàn bộ hệ thống, bên cạnh cách tránh anti-pattern và refactor test song song với code production.

Ai nên đọc, và đọc theo thứ tự nào

Cuốn sách do Manning xuất bản tháng 1/2020, dày 304 trang. Trên trang của mình, Khorikov gọi đây là hướng dẫn trọn vẹn về unit testing, và cho rằng các quy tắc lập trình nên được suy ra từ lập luận nền tảng.

Manning nói rõ cuốn sách viết cho người đã biết unit test cơ bản. Nếu bạn chưa từng viết test, hãy học một framework trước rồi quay lại sau. Ví dụ trong sách viết bằng C#, nhưng nhà xuất bản khẳng định chúng áp dụng được cho mọi ngôn ngữ.

Nếu thời gian của bạn bị lịch khách hàng chia nhỏ, có thể đọc theo thứ tự này. Bắt đầu với bài blog “When to Mock”, đọc hết trong một buổi tối.

Sau đó đọc phần sách về bốn trụ cột, vì đó là bộ tiêu chí bạn sẽ dùng để chấm từng test. Cuối cùng đọc phần mock và integration test, với code bạn đang viết mở ngay bên cạnh.

Lời hứa của Manning là giúp bạn cải thiện bộ test sẵn có bằng các thực hành hiện đại, và lời hứa này khớp với thực tế của FDE. Hiếm khi bạn được viết test từ đầu. Thường thì bạn kế thừa một repo của khách, đã có sẵn những test chậm, giòn và mock khắp nơi.

Biến cuốn sách thành điểm cộng khi đi phỏng vấn

Phần lớn ứng viên chỉ ghi trong CV một dòng kiểu “viết unit test”. Bạn có thể ghi cụ thể hơn, chẳng hạn: integration test chạy trên database thật, mock chỉ đặt ở biên API dùng chung với hệ thống khác, và bộ test vẫn ổn định khi đội của khách refactor sau bàn giao.

Dòng đó cho nhà tuyển dụng thấy bạn hiểu chuyện bàn giao, chứ không chỉ biết cú pháp.

Trong phỏng vấn, nếu được hỏi về chiến lược test cho một hệ thống tích hợp, hãy trả lời bằng sự đánh đổi chứ không bằng tỷ lệ coverage. Nói rõ bạn chọn hai trong ba trụ cột nào cho từng lớp test và vì sao. Đó đúng là cách suy nghĩ đi từ nền tảng mà Khorikov đề cao.

Khi bạn rời site, code của bạn vẫn ở lại. Bộ test là thứ sẽ thay bạn trả lời những câu hỏi mà đội của khách chưa kịp hỏi.

Bài này có hữu ích không?

Dùng cùng trợ lý AIHỏi Claude ↗Hỏi ChatGPT ↗
4 nguồn
Đọc tiếp trên lộ trình · Chặng 6: Đo lườngKhoá Evaluating Generative AI dài 47 phút, phần LLM chỉ có 14 phútPhần còn lại vẫn đáng xem, vì thói quen ghi log và version dữ liệu dùng được ở mọi stack.