Unit Testing: 12 lời khuyên khi dùng


Unit Testing là một trong các thành phần chính của Agile Software Development. Được giới thiệu đầu tiên bởi Kent Beck, unit testing đã trở thành một thành phần không thể thiếu trong các hệ thống của các tổ chứ lớn nhỏ. Unit tests giúp các kỹ sư giảm thiểu số lỗi, thời gian để debugging, góp phần làm tăng sự ổn định, bền vững.
Trong bài viết này, chúng tôi sẽ tìm hiểu các bước để các LTV dùng unit testing trong các hệ thống phần mềm, không liên quan đến ngôn ngữ lập trình hay môi trường phát triển.

1. Unit Test quản lý rủi ro của bạn


Với một newbie, có lẽ sẽ hỏi Tại sao tôi phải viết test? Suy nghĩ Unit test là một việc làm tẻ nhạt, những kỹ sư phần mềm muốn outsource để tránh nó đi. Đó là tâm lý mà không còn chỗ trong công nghệ phần mềm hiện đại. Mục đích của những nhóm phần mềm là sản xuất phần mềm có chất lượng cao nhất.
Khách hàng và những nhà doanh nghiệp luôn than phiền về những lỗi của các phần mềm trong những năm 80 và 90. Nhưng với sự phong phú của các thư viện, dịch vụ web và các môi trường phát triển cung cấp các tính năng như refactoring và unit testing, sẽ không cònn chỗ đứng cho phần mềm có sai sót.
Ý tưởng đằng sau của Unit Test là tạo ra một tập hợp những lớp test cho mỗi thành phần của phần mềm. Unit Test tạo điều kiện thuận lợi cho việc test phần mềm liên tục, không giống những tài liệu về test, sẽ ít tốn kém khi thực hiện chúng nhiều lần.
Unit test sẽ lớn lên theo hệ thống. Mỗi test là một hợp đồng bảo hiểm mà hệ thống làm việc. Việc dùng một tập hợp unit test, những kỹ sư có thể giảm bớt đáng kể số lượng lỗi và nguy cơ với code chưa được test.

2. Viết Test Case trên thành phần cơ bản


Khi bạn bắt đầu sử dụng unit testing, luôn luôn phải hỏi Test là cái gì mà tôi phải viết?
Có một suy nghĩ sai là viết cụm của các hàm test dùng để thăm dò chức năng nào đó trong hệ thống. Bạn phải suy nghĩ rằng: cần tạo một test case (tập hợp các test) cho mỗi thành phần cơ bản nhất.
Tiêu điểm của test là một thành phần tại một thời điểm. Bên trong mỗi thành phần, tìm kiếm một thành phần có thể tương tác – bao gồm các thuộc tính được truy xuất ra bên ngoài. Bạn cần phải viết ít nhất một test trên mỗi phương thức public.

3. Tạo Abstract Test Case và Test Utilities


Với bất kỳ đoạn code nào, ở đây sẽ có những thứ chung mà tất cả các test của bạn cần làm. Bắt đầu với việc tìm thấy unit testing cho ngôn ngữ của bạn. Ví dụ trong java, những kỹ sư dùng Junit - một framework đơn giản nhưng mạnh để viết test trong java. Framework có lớp TestCase, lớp căn bản cho tất cả các test. Thêm vào những phương thức tiện ích thích hợp với môi trường của bạn. Tất cả các trường hợp test đều có thể chia sẽ tài nguyên chung này.

4. Viết những lớp test khôn khéo


Test thì cần nhiều thời gian, vì thế cần đảm bảo là test của bạn hiệu quả. Một lớp test tốt sẽ thăm dò ứng sử chính của mỗi thành phần, nhưng làm việc đó với code ít nhất có thể. Ví dụ, bạn chẳng cần viết test cho phương thức getter và setter trong Java Bean, nhưng nó sẽ vẫn được test thông qua các test khác cần thiết hơn.
Thay vào đó, viết test tập trung vào các ứng xử của hệ thống. Bạn không cần viết một cách hoàn thiện, hãy tạo những test có ý nghĩa bây giờ, rồi để thêm về sau nữa.

5. Thiết lập môi trường trong sạch cho mỗi test


Người ta luôn quan tâm đến hiệu quả. Vì vậy khi nghe rằng test cần thiết lập môi trường riêng rẽ, họ thường lo lắng về cách thực hiện. Tuy thế thiết lập mỗi test chính xác và từ đầu là quan trọng. Đảm bảo rằng mỗi test được thiết lập đúng mức và không lo lắng về hiệu quả.
Trong trường hợp khi bạn có môi trường chung cho tất cả các test - không cần thay đổi khi chạy – bạn có thể thêm static vào lớp test căn bản của bạn

6. Dùng Mock object để test có hiệu quả


Thiết lập test thì ko đơn giản, và cái nhìn đầu tiên thỉnh thoảng dường như không thể đạt được. Ví dụ, nếu sử dụng Amazon Web Services trong code của bạn, bạn có thể mô phỏng nó như thế nào trong lớp test mà không có sự tác động hệ thống thật sự.
Có một số ít cách. Bạn có thể tạo ra dữ liệu giả và sử dụng nó trong những lớp test. Trong hệ thống mà có những người sử dụng, một tập hợp riêng biệt những tài khoản có thể được dùng riêng cho việc test, được gọi là những mẫu hay những Mock object.
Việc chạy test thường xuyên có thể ảnh hưởng đến hệ thống: nếu điều gì đó trục trặc và bạn xoá dữ liệu người dùng thực tế, giải pháp là dùng dữ liệu giả
Một đối tượng giả thi hành interface đặc biệt, nhưng trả về kết quả đựơc xác định trứơc. Ví dụ, bạn có thể tạo ra đối tượng giả cho Amazon S3 mà luôn luôn đọc đựơc file từ đĩa local của bạn. Đối tượng giả có ích khi test hệ thống phức tạp với nhiều thành phần. Trong Java, có vài framework giúp tạo những đối tượng giả, đáng chú ý là JMock

7. Refactor test khi bạn refactor code


Việc test chỉ đựơc trả tiền nếu bạn thật sự đầu tư vào nó. Không chỉ bạn cần viết test, bạn cũng cần đảm bảo chúng được cập nhật. Khi thêm một phương pháp mới vào một thành phần, bạn cần thêm một hoặc nhiều test tương ứng. Bạn phải làm sạch những code không dùng bên ngoài , đồng thời loại bỏ những test không còn thích hợp nữa.
Unit test đặc biệt có ích khi làm refactoring trên diện rộng. Refactoring tập trung vào việc duy trì tính ổn định của code để giúp nó giữ ở trạng thái đúng. Sau khi bạn chỉnh sửa test, chạy lại các test có liên quan để đảm bảo bạn không làm hỏng bất cứ thứ gì khi thay đổi hệ thống.

8. Viết test trước khi sửa lỗi


Unit test là vũ khí hiệu quả trong sự đấu tranh chống lại những sai sót. Khi bạn sơ hở một vấn đề trong code của bạn, viết test trình bày vấn đề này trước khi chỉnh code. Theo cách này, nếu lỗi lại xuất hiện, nó sẽ bị bắt bởi test.
Điều này là quan trọng vì bạn không thể luôn luôn viết test đúng hoàn toàn. Khi bạn thêm test một sai sót, thì bạn đang lấp đầy lỗ hỏng trong test của chính bạn.

9. Unit Tests đảm bảo tính thực thi


Chẳng nhửng đảm bảo tính chính xác của code, unit tests còn chắc rằng thự thi của code không có suy biến, giúp cải thiện tốc độ thực thi của hệ thống.
Để viết một performance tests, bạn cần implement chức năng start và stop trong test class. Khi thích hợp, bạn có thể dùng một phương thức bất kỳ có liên quan đến thời gian hay code ước lượng thời gian chạy.

10. Test tính đồng thời


Code đồng thời rất khó khăn và là điển hình của source có nhiều lỗi. Đó cũng là lý do mà test này là rất quan trọng. Cách để làm là sử dụng sleep và locks. Bạn có thể viết trong sleep gọi test của bạn nếu bạn cần đợi một trạng thái đặc biệt của hệ thống. Trong khi đây không là giải pháp đúng 100%, chỉ đúng trong một số trường hợp. Để mô phỏng sự đồng thời trong một kịch bản phức tạp hơn, bạn cần lock thành công các đối tượng mà bạn đang test. Vì vậy bạn chỉ có thể mô phỏng hệ thống đồng thời nhưng tuần tự.

11. Chạy Test liên tục


Điểm cần chú ý của test là chạy chúng liên tục, đặc biệt là trong những team lớn, có nhiều người phát triển trên một code căn bản. Bạn có thể thiết lập test để chạy sau vài giờ một lần, hay bạn có thể chạy chúng trên mỗi lần check-in code, hay mỗi ngày (có thể là hằng đêm). Hãy quyết định phưong thức thích hợp nhất cho dự án của bạn và làm những test chạy tự động và liên tục.

12. Vui với Test!


Quan trọng là bạn vui với nó. Lần đầu tiên tôi gặp unit testing, tôi luôn nghi ngờ và nghĩ nó là công việc phụ. Nhưng tôi đã thay đổi cách nghĩ, vì một người rất thông minh mà tôi luôn tin cậy nói với tôi rằng nó rất hữu ích.
Unit testing đặt trí tuệ của bạn vào trong trạng thái mà nó rất khác với trạng thái code. Nó kích thích suy nghĩ của bạn về một việc đơn giản là làm sao tập hợp các test cần thiết cho thành phần này.

Nguồn: ReadWriteWeb

Đọc tiếp >>

Cao Trong Hien