Categories
Dev's Corner

Unit Test là gì? Vai trò của Unit Test trong phát triển phần mềm

Quy trình testing bao gồm nhiều bước kiểm thử. Unit Test (Kiểm thử đơn vị) là mức kiểm thử đầu tiên nhưng giữ vai trò không kém phần quan trọng đảm bảo sản phẩm phần mềm chất lượng đến tay người dùng.

Unit testing – bước kiểm thử đầu tiên trong quy trình Software Testing
Unit testing – bước kiểm thử đầu tiên trong quy trình Software Testing. Ảnh: TestOrigen

Dừng lại chút nào, nếu bạn đang #open_to_work, thử nghía qua các công việc đang tuyển trên Gamba nhé. Vào LINK NÀY để xem các job Testing hoặc scan QR Code ở bên dưới nhé.

Xem và ứng tuyển các job "testing"
Xem và ứng tuyển các job “testing”

Unit test là gì?

Unit là thành phần nhỏ nhất trong phần mềm, có thể là các hàm (Function), thủ tục (Procedure), lớp (Class), hoặc các phương thức (Method).

Unit test là một loại kiểm thử phần mềm với mục tiêu cô lập và xác minh tính chính xác của một đơn vị.

Việc phát hiện lỗi, xác định nguyên nhân và khắc phục trở nên dễ dàng hơn khi chỉ khoanh vùng trong phạm vi một Unit đang kiểm tra.

Một ví dụ về Unit test case
Một ví dụ về Unit test case. Ảnh: jeff.wilcox.name

Thực hiện kiểm thử trên đơn vị càng nhỏ thì càng tốt. Khi đó, bạn sẽ hiểu chi tiết hơn về cách code hoạt động. Không những vậy, tốc độ test sẽ nhanh hơn, nhiều Unit test sẽ được hoàn thành hơn.

Ai thực hiện Unit test?

Do Unit test được tiến hành trong quá trình lập trình, người thực hiện Unit test có thể chính là người viết phần mềm, đôi khi cũng có thể là QA/QC.

Unit test nếu được thực hiện từng bước, không sử dụng công cụ hỗ trợ thì được gọi là Phương pháp kiểm thử thủ công (Manual Unit testing).

Ngược lại, nếu có sự trợ giúp của công cụ để test nhanh hơn, chính xác hơn chính là Phương pháp kiểm thử tự động (Automated Unit testing).

Các phương pháp kiểm thử tự động sử dụng trong Automated Unit testing: black box testing, white box texting và gray box testing.

Đa số trường hợp Developer sẽ tiến hành Unit testing
Đa số trường hợp Developer sẽ tiến hành Unit testing. Ảnh: Unplash

Các bước trong Unit test

Một Unit test điển hình sẽ trải qua 3 giai đoạn, được biết đến với tên gọi AAA:

  • Arrange: xác định thành phần của ứng dụng bạn muốn kiểm thử trong SUT (system under test)
  • Act: Giả lập trong SUT
  • Assert: Quan sát kết quả

Nếu kết quả quan sát được đúng như kỳ vọng, Unit test được xem là hoàn thành (pass). Nếu không, nó sẽ báo lỗi (fail), tức là đã có vấn đề ở đâu đó trong SUT.

Vai trò của Unit test

Công việc viết Test case cho Unit test mất khá nhiều thời gian, thậm chí đôi khi hơn cả việc coding.

Tuy nhiên, Unit test đặc biệt không thể bỏ qua trong các bước của quá trình kiểm thử bởi vì những lợi ích mà nó mang lại cho quá trình phát triển phần mềm như sau:

  • Unit test được thực hiện trên những thành phần rất nhỏ của code hoặc những chức năng đơn lẻ, vì vậy, trường hợp tìm ra vấn đề hay thiếu sót sẽ độc lập và không ảnh hưởng đến các test case khác.
  • Thông qua Unit test, nếu sớm phát hiện ra lỗi hay sai sót sẽ rất có ích và giảm bớt được chi phí toàn dự án. Khi Unit test được hoàn tất trước khi tích hợp code,  những sai sót hay lỗi tìm thấy sẽ dễ dàng được giải quyết mà hầu như không mang lại ảnh hưởng gì đáng kể.
  • Các Unit test case đơn giản hóa và giúp việc kiểm tra code nhẹ nhàng hơn. Về sau nếu có cần giải quyết lỗi thì cũng chỉ phải test đoạn code được chỉnh sửa mới nhất.
  • Unit testing tự động (Automated Unit testing) giúp giảm thiểu số bugs khi chạy trên môi trường production.
  • Điểm cộng nữa của Unit test đó là tạo điều kiện cho thay đổi, làm tiền đề cho phương pháp Agile, tiết kiệm thời gian và thúc đẩy tiến độ tổng thể của dự án.
  • Trên phương diện thiết kế, Unit test nhắc nhở người lập trình trước khi bắt đầu viết code, phải tập trung để đưa ra các thiết kế thật ổn. Việc kiểm thử code trong giai đoạn ban đầu có thể phát hiện các vấn đề, xử lý hệ thống và các mô hình thiết kế từ sớm.

Thêm vào đó, Unit test còn giúp ích trong việc giải phóng các chuyên viên QA khỏi những công việc kiểm tra mang tính chất phức tạp, đồng thời cũng là công cụ đánh giá năng suất và tốc độ làm việc, dựa trên số lượng các test case đạt trạng thái “pass”.

Unit test góp phần không nhỏ vào sự thành công của dự án
Unit test góp phần không nhỏ vào sự thành công của dự án. Ảnh: freepik

Unit test thật sự có thể cải thiện đáng kể chất lượng sản phẩm phần mềm của bạn.

Kinh nghiệm thực tiễn cho thấy bất kỳ dự án nào cũng cần thực hiện Unit test, đặc biệt là những dự án lớn.

Để tạo ra những Unit test case tối ưu, chúng ta cần không ngừng thực hành và học hỏi. Với những lợi ích mà Unit test mang lại, nó xứng đáng dành được một vị trí quan trọng, không thể tách rời trong quy trình kiểm thử.

Gambaru Team.

Categories
Dev's Corner

Làm thế nào để viết một unit test hiệu quả?

Viết unit test là một phần quan trọng của quá trình phát triển phần mềm bởi khi làm chính xác và hiệu quả, bạn có thể giảm đáng kể số lượng bug và đẩy nhanh tiến độ công việc.

Hãy cùng Gambaru xem qua một số cách tiếp cận viết unit test sau
Hãy cùng Gambaru xem qua một số cách tiếp cận viết unit test sau! Nguồn ảnh: freepik

Kiểm thử phương thức (method) với business logic

Giả sử ta có lớp Story với phương thức publish. Ta chỉ được phép publish một story nếu nó có trạng thái DRAFT.

Kiểm thử phương thức với Business Logic
Xem code gốc.

Trong trường hợp này, sẽ hợp lý nếu viết bài unit test cho phương thức này bởi nó chứa một quy tắc nghiệp vụ quan trọng.

Ta cần tạo hai bài unit test để bao quát hoàn toàn được quy tắc này:

  • Kiểm tra xem có xuất hiện Error khi trạng thái không phải là DRAFT hay không.
  • Kiểm tra xem liệu trạng thái có chuyển đổi thành Published khi trạng thái là DRAFT hay không.
Kiểm thử phương thức
Xem code gốc.

Chỉ bằng cách kiểm thử phương thức, ta có thể giữ cho các bài unit test ở mức nhỏ. Điều này đặc biệt hữu ích khi kiểm tra business logic khó.

Hãy cố gắng luôn bao quát mọi nhánh trong business logic của mình.

Ngoài ra, sử dụng công cụ báo cáo code coverage để thống kê phần trăm code đã được kiểm thử cũng là một thực tiễn tốt.

Giả lập các thành phần phụ thuộc

Trong một số trường hợp, để đảm bảo rằng mình chỉ đang kiểm tra business logic, bạn sẽ cần giả lập các thành phần phụ thuộc (mock the dependencies). Hãy sử dụng ví dụ sau:

Giả lập các thành phần phụ thuộc

Dịch vụ này có một phụ thuộc vào một event dispatcher. Cần phải giả lập phụ thuộc này vì ta không muốn dispatch MoneyTransferredEvent trong quá trình tiến hành làm unit test.

Ta chỉ muốn biết liệu dịch vụ này có xử lý tất cả các business logic như mong đợi hay không.

Giả lập các thành phần phụ thuộc
Xem code gốc.

Khi giả lập phụ thuộc này, ta có thể thay thế triển khai thực tế bằng triển khai “giả” (fake implementation) và sử dụng triển khai giả này để kiểm tra xem phương thức chính xác đã được gọi hay chưa.

Một giả lập cũng có thể trả về dữ liệu. Điều này có thể hữu ích khi ta giả lập repository chẳng hạn.

Hãy giữ các bài unit test ở mức độ nhỏ và chi tiết. Nếu có các assertion không liên quan trong một bài unit test, bạn có thể xem xét việc tách chúng thành nhiều bài unit test. Dưới đây là một ví dụ:

Tách thành nhiều bài unit test
Xem code gốc.

Bằng cách tách các assertion này ra, bạn sẽ biết trực tiếp phần nào của ứng dụng không hoạt động khi bài unit test không thành công.

Kiểm thử mô-đun

Đôi khi, sẽ hữu ích hơn khi kiểm thử toàn bộ mô-đun thay vì viết một bài unit test cho mọi phương thức.

Giả sử chúng ta có một số code cho cronjob trong ứng dụng của mình. Cronjob này sẽ tìm lấy tất cả các story đang chờ và publish chúng:

Kiểm thử module
Xem code gốc.

Điều quan trọng duy nhất đối với mô-đun này là nó lấy các story và publish từng story một. Viết một bài kiểm thử cho một mô-đun như thế này mang lại một số lợi ích tuyệt vời sau:

  • Bạn chỉ có thể kiểm tra những gì quan trọng: Các endpoint chính xác có được gọi với dữ liệu chính xác không?
  • Bạn có thể dễ dàng tái cấu trúc code của mình. Bài kiểm thử sẽ pass miễn là các endpoint được gọi với dữ liệu mong đợi.
  • Việc kiểm thử một mô-đun thường có thể được thực hiện nhanh hơn so với việc viết một bài kiểm thử cho mọi phương thức.

Hãy cùng xem qua bài kiểm thử mô-đun dưới đây:

Bằng cách giả lập API client, ta có thể trả về hai story. Kiểm thử sẽ pass nếu hai story này cũng được publish. Thêm một số bài kiểm thử khác cho các kết quả API khác nhau cũng là một ý hay.

Một lựa chọn tốt khác để kiểm thử các mô-đun là viết các bài kiểm tra tích hợp (integration test).

Tuy nhiên, lợi ích của làm unit test là bạn có thể dễ dàng chạy nó cục bộ hoặc trong một pipeline. Các bài kiểm thử mô-đun này cũng rất hữu ích cho phát triển hướng kiểm thử (test-driven development – TDD).

Nếu mô-đun chứa nhiều business logic, bạn có thể muốn thêm một số bài kiểm thử cho các quy tắc nghiệp vụ cụ thể này.

Khi bao quát được business logic trong các bài kiểm thử phương thức, các bài kiểm thử mô-đun sẽ trở nên đơn giản.

Các bài kiểm thử mô-đun sẽ vẫn hữu ích để xác nhận xem liệu tất cả các lớp có hoạt động cùng nhau như mong đợi hay không.

Kết

Tôi cực kỳ chuộng kiểm thử mô-đun vì chúng bao quát được rất nhiều code. Chúng cũng có thể hữu ích để kiểm thử dependency injection.

Tuy nhiên, chỉ viết các bài kiểm thử mô-đun thường sẽ không đủ. Sự kết hợp các bài kiểm thử mô-đun và kiểm thử phương thức sẽ mang đến nhiều lợi ích mỹ mãn.

Một điều quan trọng khác cần lưu ý là có nhiều bài kiểm thử phương thức quá có thể làm bạn chậm lại.

Ví dụ, khi thay đổi một chuỗi thành một enum, hầu hết các bài kiểm thử sẽ không thành công.

Tuy nhiên, các bài kiểm thử mô-đun vẫn sẽ pass. Vì vậy, hãy cân nhắc việc chỉ viết các bài kiểm thử này cho các phương thức chứa business logic.

Nếu bạn chưa bao giờ viết một bài unit test, lời khuyên là bạn nên bắt đầu bằng việc thử nghiệm các phương pháp nhất định.

Các bài kiểm thử mô-đun có thể hơi gian nan, phức tạp hơn – đặc biệt nếu chúng có nhiều thành phần phụ thuộc.

Quan trọng nhất là các bài kiểm thử của bạn bao quát hết logic quan trọng nhất và giúp cải thiện chất lượng code của mình
Quan trọng nhất là các bài kiểm thử của bạn bao quát hết logic quan trọng nhất và giúp cải thiện chất lượng code của mình. Ảnh: freepik

Để viết được các bài unit test hiệu quả, bạn sẽ cần tách code của mình đúng cách. Hãy tuân theo nguyên tắc SOLID.

Việc tách dự án của bạn thành các lớp khác nhau bằng cách sử dụng kiến ​​trúc đa tầng (multitier architecture) chẳng hạn, cũng có thể giúp việc kiểm thử ứng dụng dễ dàng hơn.

Theo Stein Janssen