Khi nói đến kiểm thử tự động hoặc kiểm thử đơn vị, ở bất kỳ ngôn ngữ lập trình nào cũng có hai ý kiến trái ngược nhau:
Vì vậy, với bài viết này, chúng tôi sẽ cố gắng thuyết phục người trước, đặc biệt bằng cách chứng minh việc bắt đầu thử nghiệm tự động trong Laravel dễ dàng như thế nào.
Đầu tiên hãy nói về "tại sao" và sau đó hãy xem một số ví dụ về cách thực hiện.
Kiểm tra tự động chạy các phần của mã và báo cáo bất kỳ lỗi nào. Đó là cách đơn giản nhất để mô tả chúng. Hãy tưởng tượng triển khai một tính năng mới trong một ứng dụng, sau đó trợ lý robot cá nhân sẽ đi kiểm tra tính năng mới theo cách thủ công, đồng thời kiểm tra xem mã mới có vi phạm bất kỳ tính năng cũ nào hay không.
Đây là ưu điểm chính: tự động kiểm tra lại tất cả các tính năng. Điều này có vẻ như là việc làm thêm, nhưng nếu bạn không bảo “robot” làm việc đó thì chúng ta nên làm thủ công, phải không?
Hoặc các tính năng mới có thể được phát hành mà không cần kiểm tra xem chúng có hoạt động hay không, hy vọng rằng người dùng sẽ báo cáo lỗi.
Kiểm tra tự động có thể mang lại cho chúng ta một số lợi thế:
Hãy thử tưởng tượng ứng dụng của bạn trong một hoặc hai năm nữa, với các nhà phát triển mới trong nhóm, những người không biết mã được viết từ những năm trước hoặc thậm chí cách kiểm tra nó.
Để thực hiện lần đầu tiên kiểm tra tự động trong Laravel, bạn không cần phải viết bất kỳ mã nào. Bạn đã đọc đúng. Mọi thứ đã được cấu hình và chuẩn bị trong quá trình cài đặt sẵndeficủa Laravel, bao gồm cả ví dụ cơ bản đầu tiên.
Bạn có thể thử cài đặt dự án Laravel và chạy thử nghiệm đầu tiên ngay lập tức:
laravel new project
cd project
php artisan test
Đây sẽ là kết quả trong bảng điều khiển của bạn:
Nếu chúng ta nhìn vào phần trướcdefiđêm của Laravel /tests
, chúng tôi có hai tệp:
kiểm tra/Tính năng/Ví dụTest.php :
class ExampleTest extends TestCase
{
public function test_the_application_returns_a_successful_response()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Bạn không cần biết bất kỳ cú pháp nào để hiểu điều gì đang diễn ra ở đây: tải trang chủ và kiểm tra xem mã trạng thái HTTP
nó là "200 OK
".
Còn được gọi là tên phương thức test_the_application_returns_a_successful_response()
trở thành văn bản có thể đọc được khi bạn xem kết quả kiểm tra, chỉ bằng cách thay thế ký hiệu gạch chân bằng dấu cách.
test/Unit/ExampleTest.php :
class ExampleTest extends TestCase
{
public function test_that_true_is_true()
{
$this->assertTrue(true);
}
}
Có vẻ hơi vô nghĩa, kiểm tra xem điều này có đúng không?
Chúng ta sẽ nói cụ thể về bài kiểm tra đơn vị sau. Hiện tại, bạn cần hiểu điều gì thường xảy ra trong mỗi bài kiểm tra.
/tests
là một lớp PHP mở rộng TestCase của Đơn vị PHPVề mặt cấu trúc, đó là tất cả những gì bạn cần biết, mọi thứ khác phụ thuộc vào chính xác những điều bạn muốn kiểm tra.
Để tạo một lớp kiểm tra trống, chỉ cần chạy lệnh này:
php artisan make:test HomepageTest
Tệp được tạo tests/Feature/HomepageTest.php
:
class HomepageTest extends TestCase
{
// Replace this method with your own ones
public function test_example()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Bây giờ chúng ta hãy xem điều gì sẽ xảy ra nếu các xác nhận kiểm tra không trả về kết quả như mong đợi.
Hãy thay đổi các bài kiểm tra ví dụ này:
class ExampleTest extends TestCase
{
public function test_the_application_returns_a_successful_response()
{
$response = $this->get('/non-existing-url');
$response->assertStatus(200);
}
}
class ExampleTest extends TestCase
{
public function test_that_true_is_false()
{
$this->assertTrue(false);
}
}
Và bây giờ, nếu chúng ta chạy lệnh php artisan test
lại:
FAIL Tests\Unit\ExampleTest
⨯ that true is true
FAIL Tests\Feature\ExampleTest
⨯ the application returns a successful response
---
• Tests\Unit\ExampleTest > that true is true
Failed asserting that false is true.
at tests/Unit/ExampleTest.php:16
12▕ * @return void
13▕ */
14▕ public function test_that_true_is_true()
15▕ {
➜ 16▕ $this->assertTrue(false);
17▕ }
18▕ }
19▕
• Tests\Feature\ExampleTest > the application returns a successful response
Expected response status code [200] but received 404.
Failed asserting that 200 is identical to 404.
at tests/Feature/ExampleTest.php:19
15▕ public function test_the_application_returns_a_successful_response()
16▕ {
17▕ $response = $this->get('/non-existing-url');
18▕
➜ 19▕ $response->assertStatus(200);
20▕ }
21▕ }
22▕
Tests: 2 failed
Time: 0.11s
Có hai bài kiểm tra không đạt, được đánh dấu là THẤT BẠI, kèm theo phần giải thích bên dưới và các mũi tên chỉ vào dòng chính xác của các bài kiểm tra không đạt. Lỗi được chỉ định theo cách này.
Giả sử chúng ta có một biểu mẫu và cần kiểm tra nhiều trường hợp khác nhau: chúng ta kiểm tra xem nó có bị lỗi với dữ liệu không hợp lệ hay không, chúng ta kiểm tra xem nó có thành công với dữ liệu đầu vào chính xác hay không, v.v.
Bộ khởi động chính thức bởi Laravel Breeze bao gồm tôi kiểm tra chức năng bên trong nó. Hãy xem xét một số ví dụ từ đó:
tests/Feature/RegistrationTest.php
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_registration_screen_can_be_rendered()
{
$response = $this->get('/register');
$response->assertStatus(200);
}
public function test_new_users_can_register()
{
$response = $this->post('/register', [
'name' => 'Test User',
'email' => 'test@example.com',
'password' => 'password',
'password_confirmation' => 'password',
]);
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
}
}
Ở đây, chúng tôi có hai bài kiểm tra trong một lớp, vì cả hai đều liên quan đến biểu mẫu đăng ký: một bài kiểm tra xem biểu mẫu có được tải chính xác hay không và bài kiểm tra khác kiểm tra xem việc gửi có hoạt động tốt hay không.
Chúng ta hãy làm quen với hai phương pháp nữa để xác minh kết quả, hai khẳng định nữa: $this->assertAuthenticated()
e $response->assertRedirect()
. Bạn có thể kiểm tra tất cả các xác nhận có sẵn trong tài liệu chính thức của Đơn vị PHP e Phản hồi của Laravel . Lưu ý rằng một số khẳng định chung xảy ra về chủ đề này $this
, trong khi những người khác kiểm tra cụ thể $response
từ cuộc gọi định tuyến.
Một điều quan trọng nữa là use RefreshDatabase;
câu lệnh, có nét, được chèn phía trên lớp. Điều này là cần thiết khi các hành động kiểm tra có thể ảnh hưởng đến cơ sở dữ liệu, như trong ví dụ này, việc ghi nhật ký sẽ thêm một mục mới vào users
bảng cơ sở dữ liệu. Đối với điều này, bạn nên tạo một cơ sở dữ liệu thử nghiệm riêng sẽ được cập nhật với php artisan migrate:fresh
mỗi lần chạy thử nghiệm.
Bạn có hai tùy chọn: tạo cơ sở dữ liệu riêng biệt hoặc sử dụng cơ sở dữ liệu SQLite trong bộ nhớ. Cả hai đều được cấu hình trong tập tin phpunit.xml
được cung cấp theo mặc địnhdefiNita với Laravel. Cụ thể, bạn cần phần này:
<php>
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="MAIL_MAILER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
Xem DB_CONNECTION
e DB_DATABASE
những cái nào được bình luận? Nếu bạn có SQLite trên máy chủ của mình, hành động đơn giản nhất là chỉ cần bỏ ghi chú những dòng đó và các thử nghiệm của bạn sẽ chạy dựa trên cơ sở dữ liệu trong bộ nhớ đó.
Trong thử nghiệm này, chúng tôi nói rằng người dùng đã được xác thực thành công và được chuyển hướng đến đúng trang chủ, nhưng chúng tôi cũng có thể kiểm tra dữ liệu thực tế trong cơ sở dữ liệu.
Ngoài mã này:
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
Chúng ta cũng có thể sử dụng các xác nhận kiểm tra cơ sở dữ liệu và làm một cái gì đó như thế này:
$this->assertDatabaseCount('users', 1);
// Or...
$this->assertDatabaseHas('users', [
'email' => 'test@example.com',
]);
Bây giờ chúng ta hãy xem một ví dụ khác về trang Đăng nhập với Laravel Breeze
tests/Feature/AuthenticationTest.php:
class AuthenticationTest extends TestCase
{
use RefreshDatabase;
public function test_login_screen_can_be_rendered()
{
$response = $this->get('/login');
$response->assertStatus(200);
}
public function test_users_can_authenticate_using_the_login_screen()
{
$user = User::factory()->create();
$response = $this->post('/login', [
'email' => $user->email,
'password' => 'password',
]);
$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);
}
public function test_users_can_not_authenticate_with_invalid_password()
{
$user = User::factory()->create();
$this->post('/login', [
'email' => $user->email,
'password' => 'wrong-password',
]);
$this->assertGuest();
}
}
Đó là về hình thức đăng nhập. Logic tương tự như đăng ký phải không? Nhưng ba phương pháp thay vì hai, vì vậy đây là một ví dụ về việc thử nghiệm cả tình huống tốt và xấu. Vì vậy, logic chung là bạn nên kiểm tra cả hai trường hợp: khi mọi thứ diễn ra tốt đẹp và khi chúng thất bại.
Ngoài ra, những gì bạn thấy trong bài kiểm tra này là việc sử dụng Nhà máy cơ sở dữ liệu : Laravel tạo người dùng giả ( một lần nữa, trên cơ sở dữ liệu thử nghiệm được cập nhật của bạn ) rồi cố gắng đăng nhập bằng thông tin xác thực chính xác hoặc không chính xác.
Một lần nữa, Laravel tạo bản cài đặt gốc của nhà máydefinita với dữ liệu sai cho User
mô hình, bên ngoài hộp.
database/factories/UserFactory.php:
class UserFactory extends Factory
{
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
}
}
Bạn thấy đấy, chính Laravel đã chuẩn bị bao nhiêu thứ rồi, vậy liệu chúng ta có dễ dàng bắt đầu thử nghiệm không?
Vì vậy nếu chúng ta thực hiện php artisan test
sau khi cài đặt Laravel Breeze, chúng ta sẽ thấy một cái gì đó như thế này:
PASS Tests\Unit\ExampleTest
✓ that true is true
PASS Tests\Feature\Auth\AuthenticationTest
✓ login screen can be rendered
✓ users can authenticate using the login screen
✓ users can not authenticate with invalid password
PASS Tests\Feature\Auth\EmailVerificationTest
✓ email verification screen can be rendered
✓ email can be verified
✓ email is not verified with invalid hash
PASS Tests\Feature\Auth\PasswordConfirmationTest
✓ confirm password screen can be rendered
✓ password can be confirmed
✓ password is not confirmed with invalid password
PASS Tests\Feature\Auth\PasswordResetTest
✓ reset password link screen can be rendered
✓ reset password link can be requested
✓ reset password screen can be rendered
✓ password can be reset with valid token
PASS Tests\Feature\Auth\RegistrationTest
✓ registration screen can be rendered
✓ new users can register
PASS Tests\Feature\ExampleTest
✓ the application returns a successful response
Tests: 17 passed
Time: 0.61s
Bạn đã thấy các thư mục con tests/Feature
e tests/Unit
?.
sự khác biệt giữa chúng là gì?
Trên toàn cầu, bên ngoài hệ sinh thái Laravel/PHP, có một số loại thử nghiệm tự động. Bạn có thể tìm thấy các thuật ngữ như:
Nghe có vẻ phức tạp và sự khác biệt thực sự giữa các loại bài kiểm tra này đôi khi bị mờ đi. Đó là lý do tại sao Laravel đã đơn giản hóa tất cả các thuật ngữ khó hiểu này và nhóm chúng thành hai: đơn vị/tính năng.
Nói một cách đơn giản, kiểm tra tính năng sẽ cố gắng thực thi chức năng thực tế của ứng dụng của bạn: lấy URL, gọi API, bắt chước hành vi chính xác như điền vào biểu mẫu. Kiểm tra tính năng thường thực hiện các hoạt động tương tự hoặc tương tự như bất kỳ người dùng dự án nào sẽ thực hiện, theo cách thủ công, trong đời thực.
Bài kiểm tra đơn vị có hai ý nghĩa. Nói chung, bạn có thể thấy rằng bất kỳ thử nghiệm tự động nào đều được gọi là “thử nghiệm đơn vị” và toàn bộ quá trình có thể được gọi là “thử nghiệm đơn vị”. Nhưng trong bối cảnh giữa chức năng và đơn vị, quy trình này là về việc thử nghiệm một đơn vị mã không công khai cụ thể, một cách riêng biệt. Ví dụ: bạn có một lớp Laravel với một phương thức tính toán một số thứ, chẳng hạn như tổng giá đơn hàng kèm theo các tham số. Do đó, kiểm thử đơn vị sẽ cho biết liệu kết quả chính xác có được trả về từ phương thức đó (đơn vị mã) hay không, với các tham số khác nhau.
Để tạo bài kiểm tra đơn vị, bạn cần thêm cờ:
php artisan make:test OrderPriceTest --unit
Mã được tạo giống với mã kiểm tra đơn vị trướcdefiHệ thống Laravel:
class OrderPriceTest extends TestCase
{
public function test_example()
{
$this->assertTrue(true);
}
}
Như bạn có thể thấy, nó không tồn tại RefreshDatabase
, và đây là một trong defiđịnh nghĩa kiểm thử đơn vị phổ biến nhất: nó không chạm vào cơ sở dữ liệu, nó hoạt động như một “hộp đen”, tách biệt khỏi ứng dụng đang chạy.
Cố gắng bắt chước ví dụ tôi đã đề cập trước đó, hãy tưởng tượng chúng ta có một lớp dịch vụ OrderPrice
.
app/Services/OrderPriceService.php:
class OrderPriceService
{
public function calculatePrice($productId, $quantity, $tax = 0.0)
{
// Some kind of calculation logic
}
}
Sau đó, bài kiểm tra đơn vị có thể trông giống như thế này:
class OrderPriceTest extends TestCase
{
public function test_single_product_no_taxes()
{
$product = Product::factory()->create(); // generate a fake product
$price = (new OrderPriceService())->calculatePrice($product->id, 1);
$this->assertEquals(1, $price);
}
public function test_single_product_with_taxes()
{
$price = (new OrderPriceService())->calculatePrice($product->id, 1, 20);
$this->assertEquals(1.2, $price);
}
// More cases with more parameters
}
Theo kinh nghiệm cá nhân của tôi với các dự án Laravel, phần lớn các bài kiểm tra là kiểm tra tính năng, không phải kiểm tra đơn vị. Trước tiên, bạn cần kiểm tra xem ứng dụng của bạn có hoạt động hay không, cách người dùng thực sử dụng nó.
Tiếp theo, nếu bạn có những phép tính hoặc logic đặc biệt, bạn có thể definire là một đơn vị, với các tham số, bạn có thể tạo các bài kiểm tra đơn vị cụ thể cho điều đó.
Đôi khi, việc viết bài kiểm tra yêu cầu phải sửa đổi chính mã và tái cấu trúc nó để làm cho nó “dễ kiểm tra” hơn: tách các đơn vị thành các lớp hoặc phương thức đặc biệt.
Công dụng thực sự của cái này là gì php artisan test
, khi nào bạn nên chạy nó?
Có nhiều cách tiếp cận khác nhau, tùy thuộc vào quy trình làm việc kinh doanh của bạn, nhưng nhìn chung, bạn cần đảm bảo rằng tất cả các thử nghiệm đều “xanh” (tức là không có lỗi) trước khi đẩy các thay đổi mã cuối cùng vào kho lưu trữ.
Sau đó, bạn thực hiện nhiệm vụ của mình một cách cục bộ và khi bạn nghĩ mình đã hoàn thành, hãy chạy một số thử nghiệm để đảm bảo rằng bạn không làm hỏng bất kỳ điều gì. Hãy nhớ rằng, mã của bạn có thể gây ra lỗi không chỉ về logic mà còn vô tình phá vỡ một số hành vi khác trong mã của người khác đã viết từ lâu.
Nếu chúng ta tiến thêm một bước nữa, chúng ta có thể tự động hóa nhiều đồ đạc. Với nhiều công cụ CI/CD khác nhau, bạn có thể chỉ định các thử nghiệm sẽ chạy bất cứ khi nào ai đó đẩy các thay đổi vào một nhánh Git cụ thể hoặc trước khi hợp nhất mã vào nhánh sản xuất. Quy trình làm việc đơn giản nhất là sử dụng Github Actions, tôi có một video riêng biệt điều đó chứng minh điều đó
Có nhiều ý kiến khác nhau về mức độ của cái gọi là "phạm vi kiểm tra": thử mọi thao tác và trường hợp có thể có trên mỗi trang hoặc giới hạn công việc ở những phần quan trọng nhất.
Trên thực tế, đây là điểm tôi đồng ý với những người cáo buộc việc thử nghiệm tự động tốn nhiều thời gian hơn là mang lại lợi ích thực tế. Điều này có thể xảy ra nếu bạn viết bài kiểm tra cho từng chi tiết. Điều đó có nghĩa là dự án của bạn có thể yêu cầu nó: câu hỏi chính là “cái giá của lỗi tiềm ẩn là bao nhiêu”.
Nói cách khác, bạn cần ưu tiên nỗ lực thử nghiệm của mình bằng cách đặt câu hỏi “Điều gì sẽ xảy ra nếu mã này không thành công?” Nếu hệ thống thanh toán của bạn có lỗi sẽ ảnh hưởng trực tiếp đến doanh nghiệp. Vì vậy, nếu chức năng của vai trò/quyền của bạn bị hỏng thì đây là một vấn đề bảo mật rất lớn.
Tôi thích cách Matt Stauffer phát biểu tại một hội nghị: “Trước tiên, bạn phải kiểm tra những điều đó, nếu chúng thất bại, bạn sẽ bị sa thải khỏi công việc của mình.” Tất nhiên đó là một sự cường điệu, nhưng bạn hiểu ý: hãy thử những thứ quan trọng trước. Và sau đó là các tính năng khác, nếu bạn có thời gian.
Tất cả các ví dụ trên đều dựa trên công cụ thử nghiệm trước của Laraveldefiđêm: Đơn vị PHP . Nhưng qua nhiều năm, các công cụ khác đã xuất hiện trong hệ sinh thái và một trong những công cụ phổ biến mới nhất là CÔN TRÙNG . Được tạo bởi nhân viên chính thức của Laravel Nuno Maduro , nhằm mục đích đơn giản hóa cú pháp, giúp việc viết mã để kiểm tra nhanh hơn nữa.
Dưới mui xe, nó chạy su PHPUnit, như một lớp bổ sung, chỉ cố gắng giảm thiểu một số phần được lặp lại trước đódefiphần cuối của mã PHPUnit.
Hãy xem một ví dụ. Hãy nhớ lớp kiểm tra tính năng trướcdefiđã ở Laravel? Tôi sẽ nhắc nhở bạn:
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_the_application_returns_a_successful_response()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Bạn có biết thử nghiệm tương tự với PEST sẽ như thế nào không?
test('the application returns a successful response')->get('/')->assertStatus(200);
Có, MỘT dòng mã và thế là xong. Vì vậy, mục tiêu của PEST là loại bỏ chi phí:
Để tạo thử nghiệm PEST trong Laravel, bạn cần chỉ định một cờ bổ sung:
php artisan make:test HomepageTest --pest
Vào thời điểm viết bài này, PEST khá phổ biến đối với các nhà phát triển Laravel, nhưng việc có nên sử dụng công cụ bổ sung này và tìm hiểu cú pháp của nó hay không, cũng như ghi chú PHPUnit, là tùy thuộc vào sở thích cá nhân của bạn.
BlogInnovazione.it
Một ca phẫu thuật tạo hình mắt bằng cách sử dụng trình xem thương mại Apple Vision Pro đã được thực hiện tại Phòng khám đa khoa Catania…
Phát triển kỹ năng vận động tinh thông qua tô màu giúp trẻ chuẩn bị cho những kỹ năng phức tạp hơn như viết. Để tô màu…
Ngành hải quân là một cường quốc kinh tế toàn cầu thực sự, đang hướng tới thị trường 150 tỷ...
Thứ Hai tuần trước, Financial Times đã công bố một thỏa thuận với OpenAI. FT cấp phép cho hoạt động báo chí đẳng cấp thế giới…