Part 02 · Testing & Code Quality · 2.1.01

Chiến lược kiểm thử theo rủi ro và boundary

Test suite là một portfolio tín hiệu: mỗi lớp test mua một mức tự tin khác nhau bằng thời gian chạy, độ trung thực với production và chi phí chẩn đoán khi thất bại.


1. Mental model: test là cơ chế kiểm soát rủi ro

Đừng bắt đầu bằng câu hỏi “nên dùng annotation nào?” hoặc “cần bao nhiêu phần trăm unit test?”. Hãy bắt đầu từ failure có thể gây thiệt hại: sai business invariant, mất dữ liệu, contract không tương thích, duplicate side effect, race condition, cấu hình framework sai hoặc deployment hỏng.

Sau khi xác định rủi ro, chọn boundary nhỏ nhất nhưng vẫn tái hiện trung thực failure đó. Boundary càng nhỏ thì feedback thường càng nhanh và dễ chẩn đoán; boundary càng rộng thì tín hiệu càng gần production nhưng setup, runtime và độ bất định cũng cao hơn.

Nguyên tắc cốt lõi: framework, annotation hoặc việc test “có database” không tự quyết định loại test. Loại test được xác định bởi boundary đang kiểm tra, dependency nào là thật và guarantee nào cần chứng minh.

2. Các test boundary chính

BoundaryTín hiệu cần chứng minhVí dụĐiểm yếu chính
UnitBusiness rule và state transition trong một phạm vi nhỏ, không cần infrastructure thật.Pricing policy, validation, account state transition.Không chứng minh wiring, serialization, SQL hoặc cấu hình framework.
IntegrationSự hợp tác với database, broker, filesystem hoặc framework thật.Repository chạy với PostgreSQL; producer gửi vào broker.Setup phức tạp hơn, chạy lâu hơn và cần quản lý dữ liệu test.
ComponentMột service qua public boundary trong khi external dependencies được kiểm soát.REST API với database container và payment stub.Cần application runtime và không chứng minh toàn bộ journey liên service.
ContractConsumer và provider còn tương thích về schema, field và semantics.Order service kiểm tra contract của Payment API hoặc event schema.Không chứng minh business journey hoặc production topology hoạt động.
End-to-endCritical journey hoạt động qua deployment và các thành phần đã tích hợp.Place order → pay → confirm.Chậm, dễ flaky và khó xác định thành phần gây lỗi.

3. Test pyramid là heuristic, không phải quota

Một test suite khỏe mạnh thường có nhiều test nhỏ, nhanh và deterministic ở đáy; ít integration/component test hơn; và chỉ giữ một số E2E cho critical journeys. Pyramid không quy định một tỷ lệ cố định như 70/20/10. Kiến trúc và risk profile mới quyết định tỷ lệ phù hợp.

Feedback flow mong muốn:

  1. Code change được kiểm tra ngay bằng test nhanh cho behavior cục bộ.
  2. Integration test xác nhận adapter, schema, transaction và semantics của infrastructure.
  3. Component và contract test xác nhận public boundary giữa các thành phần.
  4. Một số ít E2E xác nhận critical journey trên deployment gần production.

Nếu cùng một defect có thể được phát hiện ổn định ở boundary hẹp hơn, nên ưu tiên boundary đó. Failure xuất hiện càng sớm và càng gần nguyên nhân thì chi phí debug càng thấp.

4. Chọn boundary bằng câu hỏi rủi ro

5. Determinism và testability

Test tốt nên hướng tới FIRST: Fast, Independent, Repeatable, Self-validating, Timely. Các nguồn nondeterminism như clock, random seed, locale, timezone, scheduler, thread coordination, network ngoài và shared mutable state phải có điểm kiểm soát.

6. Những failure mode phổ biến

Production caveat: test không thay thế canary, observability và rollback. Test làm giảm xác suất defect thoát ra ngoài và cung cấp feedback trước deployment; nó không chứng minh hệ thống không thể thất bại trong production.

7. Câu trả lời phỏng vấn mẫu

Tiếng Việt

Tôi thiết kế test suite dựa trên rủi ro và tốc độ feedback. Business rule được bao phủ bằng unit test tập trung; rủi ro tích hợp được kiểm tra với infrastructure thật; component và contract test bảo vệ public boundary; E2E chỉ dành cho critical journey. Tỷ lệ giữa các lớp không cố định mà phụ thuộc kiến trúc, chi phí failure và mức độ cần fidelity với production.

English interview answer

I optimize the test suite for fast feedback and confidence. Most business rules are covered by focused unit tests, integration risks by tests against real infrastructure, and only critical user journeys by end-to-end tests. The exact ratio depends on architecture and risk.

8. Checklist tự đánh giá

Nguồn tham khảo