Clean code series : Chương 9 - Unit test

Unit Test là một loại kiểm thử phần mềm trong đó các đơn vị hay thành phần riêng lẻ của phần mềm được kiểm thử. Kiểm thử đơn vị được thực hiện trong quá trình phát triển ứng dụng. Mục tiêu của Kiểm thử đơn vị là cô lập một phần code và xác minh tính chính xác của đơn vị đó.

Tại sao cần unit test ?
- Tăng sự tin tưởng vào mã nguồn khi có sự thay đổi hoặc bảo trì.

Phát hiện bug ngay lập trức và sửa bug nhanh hơn.

Kỹ thuật viết unit test
1/ Xây dựng theo mô hình BUILD-OPERATE-CHECK

Đảm bảo 3 bước được thể hiện rõ khi đọc code test

  • Bước 1: Tạo dữ liệu data test
  • Bước 2: Thử nghiệm dữ liệu data test đó
  • Bước 3: Kiểm tra kết quả test

Code:

Người đọc bị "phân tâm" khi phải cố gắng hiểu logic xử lý bên trong hàm test hoạt động như thế nào như PathParse thì dùng để chuyển đổi string và đối tượng crawler chuyển giá trị vào page,...

Refactored :

Tạo mới các hàm makePages, submitRequest, assertResponseIsXml, assertResponseContains để che dấu đi logic xử lý.

Kết quả:
Không bị “RỐI” trước các hàm xử lý và chỉ tập trung hiểu được flow và ý nghĩa thực sự bài toán.

2/ Áp dụng A Dual Standard ( tiêu chuẩn kép )

Khẳng định : “Tiêu chuẩn kỹ thuật trong khi viết unit test và production code là khác nhau ”.

Yêu cầu bài toán :
Hệ thống kiểm soát môi trường, cần kiểm tra nhiệt độ của các thiết bị như

  • Lò sưởi ( heater )
  • Quạt gió (blower )
  • Máy làm mát (cooler )
  • Đồng hồ báo nhiệt độ thấp ( lo-temp-alarm )
  • Đồng hồ báo nhiệt độ cao ( hi-temp-alarm )

Khi nhiệt độ môi trường là "WAY_TOO_COLD" hoặc "WAY_TOO_HOT“.

Code:

Lặp lại quá nhiều hàm check tại mỗi function test khiến người đọc bị "phân tâm".

Refactored:

Tối ưu và ngắn gọn function test với 1 hàm check nhưng nếu để ý mọi người sẽ thấy vi phạm tính minh bạch trong cách đặt tên tham số đầu vào với mỗi hàm check.
Người viết đã cố tính để tham số đầu vào là 1 chuỗi gồm 5 chữ cái với ý ngầm hiểu là các chữ cái đầu từ tiếng anh của các thiếu bị cần kiểm tra : heater, blower , cooler , lo-temp-alarm, hi-temp-alarm và nếu thiết bị được bật thì chữ cái đó sẽ được viết hoa.

Kết luận :

Tuy cách refactored code vi phạm tiêu chuẩn khi viết production code nhưng lại có thể được áp dụng trong viết test nó giúp người đọc để hiểu nhanh được flow và kết quả hàm test nếu người viết comment đủ ý cùng đảm bảm người đọc hiểu được ẩn ý => Làm rõ khẳng định trong A Dual Standard.

3/ Mỗi hàm kiểm tra kiểm tra 1 hành động duy nhất
**Code:**

Nội dung bên trong hàm test đã xử lý liên tiếp 3 lần check điều kiện hàm testAddMonths với điều kiện thêm 1 tháng và 2 tháng cùng có mối liên kết giữa các lần kiểm tra ( lần thứ 3 người viết đã truyền vào SerialDate.addMonths(1,d1)) => gây khó hiểu cho người đọc và đến đây yêu cầu người đọc phải biết kết quả trả về của nó để đặt hàm check với kết quả chính xác.

Kết luận:

Tối giản và dễ hiểu => người viết nên tách thành 3 hàm riêng biệt với các tham số đầu vào cụ thể và rõ ràng.

Tổng kết

Unit test phải đảm bảo 'F.I.R.S.T'

  • Fast : nhanh và có thể phát hiện ngay lập tức
  • Independent : tính độc lập giữa các module
  • TimeLy : viết unit test đồng thời khi viết với production code ( áp dung mô hình TDD )
  • Self-validating : kiểm tra kết quả đầu ra với 1 giá trị boolean
  • Repeatable : test được trên nhiều môi trường

Rất mong bài viết có thể giúp ích cho mọi người và nhận được sự đóng góp từ mọi người !