Software Testing

Unit Test: Viết Vì Bị Bắt Buộc, Hay Thực Sự Hiểu Vì Sao Cần

Thứ năm, 01 Th10 2026 5 phút đọc 46 lượt xem

Ở nhiều dự án, unit test là thứ phải viết cho đủ để qua được bước kiểm tra coverage trong CI. Người ta viết vội vài test case, chạy thấy xanh rồi merge. Nhưng test viết cho có và test viết vì hiểu giá trị của nó khác nhau rất xa, và sự khác biệt đó chỉ lộ ra khi dự án lớn dần.

Unit test thực chất là gì

Unit test kiểm tra một đơn vị code nhỏ nhất có thể tách riêng, thường là một hàm hoặc một phương thức, trong điều kiện cô lập với phần còn lại của hệ thống. Mục tiêu không phải chứng minh code "chạy được", mà là khẳng định code hoạt động đúng như kỳ vọng với từng loại đầu vào: trường hợp bình thường, trường hợp biên, và trường hợp lỗi.

Dấu hiệu của test viết cho có

Test viết cho có thường dễ nhận ra: chỉ kiểm tra "happy path" (đầu vào đẹp, kết quả đúng); không có assertion nào thực sự kiểm tra kết quả mà chỉ gọi hàm để tăng coverage; mock quá nhiều đến mức test chỉ đang kiểm tra chính các mock; hoặc tên test mơ hồ kiểu test1, testFunction khiến không ai biết test đang bảo vệ điều gì.

Coverage cao nhưng test kiểu này tạo ra cảm giác an toàn giả. Con số báo 90% nhưng lỗi thật vẫn lọt qua, vì không test nào thực sự kiểm tra hành vi quan trọng.

Giá trị thật của unit test

Giá trị lớn nhất của unit test không nằm ở việc bắt lỗi ngay lúc viết, mà ở tương lai. Thứ nhất, test cho phép refactor tự tin: khi sửa lại cấu trúc code, bộ test báo ngay nếu hành vi bị thay đổi ngoài ý muốn. Không có test, mỗi lần refactor là một lần đánh cược. Thứ hai, test là tài liệu sống: đọc test của một hàm thường cho biết cách dùng nó nhanh hơn đọc comment, và test không bao giờ bị lỗi thời vì nếu lỗi thời thì nó sẽ fail. Thứ ba, test phát hiện lỗi sớm nhất có thể, khi chi phí sửa còn thấp, thay vì để lỗi lọt đến môi trường staging hay production.

Một lợi ích ít người nhắc tới: code khó viết test thường là dấu hiệu code đang thiết kế chưa tốt, ví dụ một hàm làm quá nhiều việc hoặc phụ thuộc chặt vào quá nhiều thành phần khác. Việc viết test buộc người viết nhìn lại thiết kế của chính mình.

Viết test sao cho có ý nghĩa

Vài nguyên tắc đơn giản giúp test có giá trị thật: đặt tên test mô tả hành vi, ví dụ returns_zero_when_cart_is_empty thay vì testCart; mỗi test chỉ kiểm tra một hành vi; luôn có test cho trường hợp biên và trường hợp lỗi, không chỉ trường hợp đẹp; chỉ mock những phụ thuộc bên ngoài thực sự (database, API, thời gian hệ thống), không mock chính logic đang cần kiểm tra; và giữ test chạy nhanh để mọi người sẵn lòng chạy thường xuyên.

Khi bị bắt buộc viết test, nhiều người coi đó là thủ tục. Khi hiểu vì sao cần, test trở thành công cụ giúp chính người viết làm việc nhanh hơn và ngủ ngon hơn mỗi lần deploy.

Nguồn tham khảo

Sẵn sàng chuyển đổi doanh nghiệp?

Hãy thảo luận về cách chúng tôi có thể giúp bạn tận dụng AI và chuyển đổi số.

Câu hỏi thường gặp

Unit test là gì?
Là kiểm thử một đơn vị code nhỏ nhất (thường là một hàm) trong điều kiện cô lập, để khẳng định nó hoạt động đúng với từng loại đầu vào: bình thường, biên và lỗi.
Coverage cao có nghĩa là code đã được kiểm thử tốt không?
Không hẳn. Test chỉ gọi hàm mà không kiểm tra kết quả, hoặc chỉ test happy path, vẫn đẩy coverage lên cao nhưng không bắt được lỗi thật.
Lợi ích lớn nhất của unit test là gì?
Giúp refactor tự tin, đóng vai trò tài liệu sống, và phát hiện lỗi sớm khi chi phí sửa còn thấp.
Có nên mock mọi thứ khi viết unit test?
Không. Chỉ nên mock các phụ thuộc bên ngoài thực sự như database, API, thời gian hệ thống, không mock chính logic đang cần kiểm tra.
Vì sao code khó viết test lại là dấu hiệu đáng chú ý?
Vì nó thường cho thấy thiết kế chưa tốt, ví dụ hàm làm quá nhiều việc hoặc phụ thuộc chặt vào quá nhiều thành phần khác.

Chia sẻ bài viết