Hướng dẫn dùng computing abbreviation trong PHP
Trong bài đầu tiên của series này, chúng ta đã đi qua cách cài đặt và cấu hình PHPUnit cho 1 project PHP, một số conventions khi thực hiện Unit test trong PHP và trải nghiệm với unit test đầu tiên. Trong bài này, chúng ta sẽ tìm hiểu một số khái niệm quan trọng trong unit test và đi vào thực hành nhiều hơn. Show ASSERTIONSAssertion là gì? Theo định nghĩa từ Wikipedia:
Assertion chỉ đơn giản là 1 câu lệnh nhằm mục đích xác nhận một khẳng định là luôn đúng tại đoạn code đó. Hiểu theo cách khác, Assertion định nghĩa điều bạn muốn nó xảy ra (VD: Tôi muốn hàm này trả về false => tôi assert return value là false, tôi muốn hàm kia trả về mảng có chứa 5 phần tử => tôi assert array size = 5, tôi muốn kết quả thu được lơn hơn 100,...) Assertion trả về true thì sẽ pass unit test, ngược lại sẽ fail. Trong ví dụ đầu tiên:
Chúng ta đã assert rằng true là true ( if (true == true) ). Không có gì đặc biệt ở đây, điều bạn thấy là điều bạn nhận được với assertions. Nếu chúng ta assert rằng false là true, chúng ta sẽ nhận được 1 test fail:
Nhưng nếu chúng ta muốn assert rằng false là false ( if (false == false) ) thì sao?
Unit test này được pass vì câu lệnh assertion của chúng ta trả về true, mặc dù
cho phương thức được gọi là PHPUnit cung cấp rất nhiều assertions được liệt kê tại đây. Bạn không phải sử dụng tất cả. Phần lớn bạn sẽ sử dụng các assertions Unit test (có ích) đầu tiênUnit test có ích đầu tiên của chúng ta sẽ là unit test cho một hàm chuyển đổi từ string thông thường sang dạng url slug, ví dụ hàm này sẽ biến đổi chuỗi: "This string will be sluggified" sang "this-string-will-be-sluggified". Tạo file
Tôi thấy đoạn code này là ví dụ rất tốt để thực hành unit test đầu tiên vì nó dễ hiểu và có rất nhiều trường hợp có thể gây ra lỗi. Chúng ta bắt đầu viết test với file
Class Chúng ta chạy phpunit ngay sau khi tạo file test và bộ khung của nó để chắc chắn rằng chúng ta không bị lẫn lộn trong tên file hay tên test class. Điều này sẽ giúp tránh các trường hợp không mong đợi trong tương lai khi bộ test tất cả đều pass nhưng bạn nhận ra PHPUnit đã không thực sự chạy file test của bạn có thể do sai sót cách đặt tên. Bước tiếp theo, chúng ta sẽ test trường hợp đầu tiên: chúng ta muốn xác nhận rằng
Với phiên bản PHPUnit 6.2 đang dùng, PHPUnit sẽ báo warning nếu method của bạn không chưa bất cứ assertion nào: Tiếp theo, chúng ta sẽ bắt đầu viết phần thân cho test method. Mong muốn của chúng ta trong test case này là:
Để test method
Bây giờ, chúng ta sẽ lấy ra
kết quả từ phương thức
Bước cuối cùng đó là assert rằng
Chạy lại PHPUnit và xem kết quả Các kịch bản test khácUnit test khởi đầu của chúng ta đã pass, thật tuyệt. Tuy nhiên, có 1 vấn đề là chúng ta mới chỉ test 1 string chỉ chứa các ký tự A-Z và dấu cách. Điều gì sẽ xảy ra nếu string có chứa số hay các ký tự đặc biệt ( ([email protected]#$%^&*()_+))? Và với các ký tự không phải English thì sao? Trường hợp string rỗng thì như thế nào? Có quá nhiều trường hợp cần phải test. Một bộ test suite chuẩn khi nó bao phủ được tất cả các khả năng có thể xảy ra, vì vậy chúng ta sẽ viết test cho một số kịch bản khác:
Ghi
chú: do hàm
Chạy PHPUnit với CTYPE là C => Fail Danh sách các locale hệ thống hỗ trợ
Thay đổi locale => Pass Vấn đề trùng lặp codeBạn có thể dễ dàng nhận thấy code test của chúng ta đang có vấn để lớn là trùng lặp code. May mắn là PHPUnit đã có hỗ trợ công cụ để chúng ta khắc phục điều này. Annotations trong PHPUnitAnnotations là các flag đặc biệt được khai báo trong docblocks của method:
PHPUnit cung cấp rất nhiều annotations hữu ích, nhưng trước hết chúng ta đề hãy cập đến @dataProviderPHPUnit định nghĩa data providers như sau:
Tạm dịch là: 1 test method có thể chấp nhận nhiều input khác nhau. Các tham số này được cung cấp bởi method data provider. Hiểu đơn giản, 1 method data provider có thể được sử dụng để tạo ra nhiều tập input để truyền vào 1 test method, khắc phục vấn đề phải tạo nhiều method test như chúng ta đã thực hiện ở trên. Thay vì tạo ra nhiều phương thức test, bạn chỉ cần tạo ra một phương thức duy nhất với các tham số tương ứng với dữ liệu biến đổi giữa các phép thử, và tạo một phương thức cung cấp dữ liệu để test. VD:
Một method data provider trả về 1 mảng các tập input. Trong ví dụ trên, chúng ta có 5 tập input đầu vào để test. Mỗi tập là 1 mảng các các giá trị được truyền vào test method theo thứ tự trong mảng. Ví dụ với tập input đầu:
Nó sẽ được truyền vào method Bây giờ, chúng ta sẽ áp dụng vào unit test lần trước. Sửa lại file
Chạy lại PHPUnit: Huzzah! Kết luậnTrong bài này, chúng ta đã tìm hiểu về assertions, thực hành các unit test thực sự và tìm hiểu về Vẫn còn khá nhiều thứ cần phải học, nhưng trước hết bạn nên thực hành test các code đơn giản (không có phụ thuộc bên ngoài method). Trong bài tiếp theo, chúng ta sẽ học cách test các method có các dependency bên ngoài, tìm hiểu các khái niệm mocks, stubs và sự khác nhau của chúng, tìm hiểu tại sao nên hạn chế sử dụng static method và sự hữu ích của dependency injection. Hẹn gặp lại các bạn trong bài tiếp theo. |