測試:入門
簡介
Laravel is built with testing in mind. In fact, support for testing with Pest and PHPUnit is included out of the box and a phpunit.xml
file is already set up for your application. The framework also ships with convenient helper methods that allow you to expressively test your applications.
預設情況下,專案的 tests
目錄內包含了兩個目錄:Feature
與 Unit
。Unit Test 是專注於測試一些小部分、與其他部分獨立的程式碼。其實,單元測試可能會只專注於測試單一方法。在「Unit」測試目錄下的測試不會啟用 Laravel 專案,因此無法存取專案的資料庫或其他 Laravel 的服務。
Feature Test可用來測試較大部分的程式碼 —— 測試各個物件要如何互相使用、測試 JSON Endpoint 的完整 HTTP Request 等。一般來說,大多數的測試應該都是 Feature Test。使用 Feature Test 有助於確保整體系統如期運作。
An ExampleTest.php
file is provided in both the Feature
and Unit
test directories. After installing a new Laravel application, execute the vendor/bin/pest
, vendor/bin/phpunit
, or php artisan test
commands to run your tests.
環境
When running tests, Laravel will automatically set the configuration environment to testing
because of the environment variables defined in the phpunit.xml
file. Laravel also automatically configures the session and cache to the array
driver so that no session or cache data will be persisted while testing.
若有需要,也可以自行定義其他的測試環境設定值。testing
環境變數可以在專案的 phpunit.xml
檔案中修改。不過,在執行測試前,請記得使用 config:clear
Artisan 指令來清除設定快取!
.env.testing
環境檔
In addition, you may create a .env.testing
file in the root of your project. This file will be used instead of the .env
file when running Pest and PHPUnit tests or executing Artisan commands with the --env=testing
option.
建立測試
若要建立新測試例,請使用 make:test
Artisan 指令。預設情況下,測試會被放在 tests/Feature
目錄下:
1php artisan make:test UserTest
1php artisan make:test UserTest
若要在 tests/Unit
目錄下建立測試,可在執行 make:test
指令時使用 --unit
選項:
1php artisan make:test UserTest --unit
1php artisan make:test UserTest --unit
可以安裝 Stub 來自訂測試的 Stub。
Once the test has been generated, you may define test as you normally would using Pest or PHPUnit. To run your tests, execute the vendor/bin/pest
, vendor/bin/phpunit
, or php artisan test
command from your terminal:
1<?php23test('basic', function () {4 expect(true)->toBeTrue();5});
1<?php23test('basic', function () {4 expect(true)->toBeTrue();5});
1<?php23namespace Tests\Unit;45use PHPUnit\Framework\TestCase;67class ExampleTest extends TestCase8{9 /**10 * A basic test example.11 */12 public function test_basic_test(): void13 {14 $this->assertTrue(true);15 }16}
1<?php23namespace Tests\Unit;45use PHPUnit\Framework\TestCase;67class ExampleTest extends TestCase8{9 /**10 * A basic test example.11 */12 public function test_basic_test(): void13 {14 $this->assertTrue(true);15 }16}
If you define your own setUp
/ tearDown
methods within a test class, be sure to call the respective parent::setUp()
/ parent::tearDown()
methods on the parent class. Typically, you should invoke parent::setUp()
at the start of your own setUp
method, and parent::tearDown()
at the end of your tearDown
method.
執行測試
As mentioned previously, once you've written tests, you may run them using pest
or phpunit
:
1./vendor/bin/pest
1./vendor/bin/pest
1./vendor/bin/phpunit
1./vendor/bin/phpunit
In addition to the pest
or phpunit
commands, you may use the test
Artisan command to run your tests. The Artisan test runner provides verbose test reports in order to ease development and debugging:
1php artisan test
1php artisan test
Any arguments that can be passed to the pest
or phpunit
commands may also be passed to the Artisan test
command:
1php artisan test --testsuite=Feature --stop-on-failure
1php artisan test --testsuite=Feature --stop-on-failure
Running Tests in Parallel
By default, Laravel and Pest / PHPUnit execute your tests sequentially within a single process. However, you may greatly reduce the amount of time it takes to run your tests by running tests simultaneously across multiple processes. To get started, you should install the brianium/paratest
Composer package as a "dev" dependency. Then, include the --parallel
option when executing the test
Artisan command:
1composer require brianium/paratest --dev23php artisan test --parallel
1composer require brianium/paratest --dev23php artisan test --parallel
預設情況下,Laravel 會以機器上可用的 CPU 核心數來建立處理程序。不過,我們也可以使用 --processes
選項來調整處理程序的數量:
1php artisan test --parallel --processes=4
1php artisan test --parallel --processes=4
When running tests in parallel, some Pest / PHPUnit options (such as --do-not-cache-result
) may not be available.
Parallel Testing and Databases
只要你有設定主要的資料庫連線,Laravel 就會自動為每個執行測試的平行處理程序建立並 Migrate 測試資料庫。Laravel 會使用每個處理程序都不同的處理程序 Token 來作為資料庫的前置詞。舉例來說,若有兩個平行的測試處理程序,則 Laravel 會建立並使用 your_db_test_1
與 your_db_test_2
測試資料庫。
預設情況下,在不同的 test
Artisan 指令間,會共用相同的測試資料庫,以在連續呼叫 test
指令時使用這些資料庫。不過,我們也可以使用 --create-databases
選項來重新建立測試資料庫:
1php artisan test --parallel --recreate-databases
1php artisan test --parallel --recreate-databases
平行測試的 Hook
有時候,我們會需要為一些專案所使用的特定資源做準備,好讓我們能在多個測試處理程序中使用這些資源。
只要使用 ParallelTesting
Facade,就可指定要在處理程序或測試例的 setUp
或 tearDown
內要執行的特定程式碼。給定的閉包會收到 $token
與 $testCase
變數,著兩個變數中分別包含了處理程序的 Token,以及目前的測試例:
1<?php23namespace App\Providers;45use Illuminate\Support\Facades\Artisan;6use Illuminate\Support\Facades\ParallelTesting;7use Illuminate\Support\ServiceProvider;8use PHPUnit\Framework\TestCase;910class AppServiceProvider extends ServiceProvider11{12 /**13 * Bootstrap any application services.14 */15 public function boot(): void16 {17 ParallelTesting::setUpProcess(function (int $token) {18 // ...19 });2021 ParallelTesting::setUpTestCase(function (int $token, TestCase $testCase) {22 // ...23 });2425 // Executed when a test database is created...26 ParallelTesting::setUpTestDatabase(function (string $database, int $token) {27 Artisan::call('db:seed');28 });2930 ParallelTesting::tearDownTestCase(function (int $token, TestCase $testCase) {31 // ...32 });3334 ParallelTesting::tearDownProcess(function (int $token) {35 // ...36 });37 }38}
1<?php23namespace App\Providers;45use Illuminate\Support\Facades\Artisan;6use Illuminate\Support\Facades\ParallelTesting;7use Illuminate\Support\ServiceProvider;8use PHPUnit\Framework\TestCase;910class AppServiceProvider extends ServiceProvider11{12 /**13 * Bootstrap any application services.14 */15 public function boot(): void16 {17 ParallelTesting::setUpProcess(function (int $token) {18 // ...19 });2021 ParallelTesting::setUpTestCase(function (int $token, TestCase $testCase) {22 // ...23 });2425 // Executed when a test database is created...26 ParallelTesting::setUpTestDatabase(function (string $database, int $token) {27 Artisan::call('db:seed');28 });2930 ParallelTesting::tearDownTestCase(function (int $token, TestCase $testCase) {31 // ...32 });3334 ParallelTesting::tearDownProcess(function (int $token) {35 // ...36 });37 }38}
Accessing the Parallel Testing Token
若想從測試程式碼中的任何地方存取目前平行處理程序的「Token」,我們可以使用 token
方法。對於各個測試處理程序來說,平行處理程序的「Token」是一個不重複的字串,可用來在多個平行測試處理程序上為資源分段。舉例來說,Laravel 會自動將該 Token 放在各個由平行測試處理程序所建立的測試資料庫名稱後方:
1$token = ParallelTesting::token();
1$token = ParallelTesting::token();
回報測試覆蓋率
在執行專案測試時,我們可能會想判斷測試例是否有實際涵蓋到專案的程式碼、或是想知道在執行測試時到底使用到專案中多少的程式碼。若要瞭解測試覆蓋率,可在叫用 test
指令時提供 --coverage
選項:
1php artisan test --coverage
1php artisan test --coverage
Enforcing a Minimum Coverage Threshold
可使用 --min
選項來為專案定義最低測試覆蓋率門檻。若未符合該門檻,測試套件會執行失敗:
1php artisan test --coverage --min=80.3
1php artisan test --coverage --min=80.3
測試分析
Artisan 的測試執行程式中也包含了一個方便的機制,能讓我們列出專案中最慢的測試。執行 test
指令時提供 --profile
選項,就可以看到一組列表中列出了 10 個最慢的測試,讓我們能輕鬆調查可以改善哪些測試來讓測試套件執行更快:
1php artisan test --profile
1php artisan test --profile