Giới thiệu về Testing trong Laravel
Giới thiệu
1. Một số khái niệm cơ bản.
- Unit Test: Kiểm thử mức đơn vị. Trong Unit Test chúng ta sẽ kiểm thử các class, method, function, ... Mục tiêu của Unit Test là kiểm thử tính đúng đắn của mỗi đơn vị trong một dự án.
- PHP Unit: Là một unit testing framework dành cho ngôn ngữ lập trình PHP. Nó cung cấp cho người sử dụng các class, method nhằm giúp cho việc viết các đoạn mã kiểm thử trở nên nhanh chóng và tiện lợi. Trong Laravel, PHP Unit được tích hợp sắn trong Laravel
- Unit Testing/Feature Testing: Trong Laravel có hai thư mục là Unit Test và Feature Test, chúng đều có mục đích để thực hiện viết mã kiểm thử các function, method trong dự án của chúng ta. Unit Test cho phép chúng ta kiểm thử các class models, controllers, ... Mục tiêu của Unit Test là để kiểm thử tính đúng đắn của từng đơn vị trong mã nguồn. Feature Test cho phép chúng ta test các api, các kết quả trả về như Http Request, Json, ...cùng với đó là test chức năng, hiệu năng và khả năng chịu tải của ứng dụng.
- Assertion: Là câu lệnh nhằm mục đích xác nhận đúng tại một đoạn code hay một function. Hiểu theo cách ngắn gọn, Assertion sẽ là kết quả mà bạn muốn nó xảy ra. Ví dụ bạn muốn kết quả trả về là true, bạn gọi hàm assertTrue(). Và unit test được pass khi các hàm assert trả về true
Bắt đầu với PHP Unit trong Laravel
2. Cấu hình PHP Unit
Sau khi khởi tạo một Laravel Project sẽ xuất hiện file phpunit.xml
để thực hiện cấu hình PHP Unit. Một file phpunit.xml
sẽ có cấu trúc cơ bản như sau:
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
</include>
</coverage>
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="your_database"/>
<server name="DB_DATABASE" value="database_name"/>
<server name="MAIL_MAILER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
<server name="TELESCOPE_ENABLED" value="false"/>
</php>
Trong đó
color="true"
làm cho kết quả test được bôi màu.
testsuites
chứa các testsuite là các folder thực hiện kiểm thử.
thẻ server
chứa các config database.
Để chạy một unit test, ta cần tạo một file .env.testing
tương tự file .env
. Đây được coi là một file .env
để thực hiện chạy trên môi trường test.
Thực hiện cài đặt môi trường test bằng câu lệnh php artisan migrate --env=testing
3. Bắt đầu viết các Test Case
Để tạo một Feature mới chúng ta sử dụng câu lệnh:
php artisan make:test UserTest
Để tạo một Unit Test chúng ta sử dụng câu lệnh:
php artisan make:test UserTest --unit
Lưu ý: Các file trong thư mục app
nên ánh xạ với các file trong thư mục test
Sau khi thực hiện một trong hai câu lệnh, Laravel sẽ generate cho chúng ta một file có nột dung như sau
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserTest extends TestCase
{
/**
* A basic unit test example.
*
* @return void
*/
public function testExample()
{
$this->assertTrue(true);
}
}
Để tạo một function test cho một đối tượng bất kì thì tên các function test chúng ta đặt luôn bắt đầu với chữ test VD: testUserCanLogin
Tên phương thức test thường sẽ có 2 cách để đặt
test_user_login_passed()
testUserRegisterPassed()
Tiến hành viết TestCase đầu tiên
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class UserTest extends TestCase
{
use RefreshDatabase;
public function setUp() : void
{
parent::setUp();
// chạy passport trước khi thực hiện test tránh lỗi personal client not found
$this->artisan('passport:install');
// chuẩn bị sẵn data mẫu
User::factory()->create();
}
/**
* A basic unit test example.
*
* @return void
*/
public function testApiClientLoginPassed()
{
$data = ['email' => $this->user->email, 'password' => '123'];
$response = $this->json('POST', '/login', $data);
$response->assertStatus(Response::HTTP_ACCEPTED)->assertJsonStructure(['data']);
}
}
Ở đây có $data
chứa các thông tin truyền vào một form bao gồm email
và password
. Function testApiClientLoginPassed
thực hiện tương tự như người dùng đang nhập thông tin để thực hiện đang nhập. $response
gọi đến phương thức POST
với uri là /login
với data truyền vào. Mong muốn sau khi thực hiện sẽ nhận được HTTP_REQUEST
là HTTP_ACCEPTED
.
Chúng ta nên tạo với function được test một function test đúng và một function test sai (Tuy nhiên test vẫn phải pass)
Một class test tiêu chuẩn bao gồm 3 bước:
-
Chuẩn bị môi trường
-
Thực hiện test
-
Assertion
Ngoài ra chúng ta có thể sử dụng nhiều hàm assert khác nhau. Sau đây là một số hàm assert:
- assertEquals($variable1, $variable2) : pass nếu hai giá trị
$variable1
và$variable2
bằng nhau. - assertNotEquals($variable1, $variable2) : Ngược lại hàm
assertEquals()
- assertSame($variable1, $variable2) : pass nếu hai giá trị có cùng kiểu và giá trị, tương tự với so sánh ===
- assertTrue($variable) : pass nếu giá trị của
$variable
là true. - assertJson($variable) : pass nếu giá trị trả về là Json và giống với
$variable
- assertStatus($status) : pass nếu giá trị trả về có Http Status giống với
$status
Tham khảo thêm : https://phpunit.readthedocs.io/en/9.5/assertions.html
4. Tiến hành chạy TestCase
Chúng ta có hai cách để run test case:
-
php artisan test
và./vendor/bin/phpunit
để thực hiện run tất cả các class test hiện có thể run. -
./vendor/bin/phpunit file
để thực hiện run một class test chỉ định.
Kết quả nhận được
PHPUnit 9.5.6 by Sebastian Bergmann and contributors.
. 1 / 1 (100%)
Time: 00:04.727, Memory: 24.00 MB
OK (1 test, 1 assertion)
5. Lưu ý
-
PHPUnit không thể chạy các test với các phương thức
protected
vàprivate
, nên các bạn phải để modify của function test làpublic
. Chúng ta cũng có thể dễ dàng tìm ra được filephpunit.xml
, PHPUnit sẽ tự xác định vị trí cho tên file được đặt tên trongphpunit.xml
hoặcphpunit.xml.dist
ở trong thư mục thực thi hiện tại. Ở trong file này, chúng ta có thể cấu hình cụ thể sự thực thi cho test của mình. -
Trong mỗi các file test chúng ta tạo ra đều use trait
RefreshDatabase
. Trait này nhằm mục đích remove tất cả các data chúng ta tạo trong quá trình run unit test. -
Trong mỗi Class Test chúng ta có thể thêm function
setUp() : void
chứa data để chạy và functiontearDown() : void
để hủy các phần chúng ta đã tạo ởsetUp
Kết luận
Chúng ta đã tìm hiểu tổng quan về PHP Unit trong Laravel, cách config, viết một kịch bản test và thực hiện run một kịch bản.
Vẫn còn rất nhiều thứ để học nhưng tổng quan với những hướng dẫn trên, chúng ta có thể tạo những kịch bản test đơn giản để tiến hành kiểm thử cho dự án của mình.