測試:入門

簡介

Laravel 在設計時就已將測試考慮進去。而且,Laravel 有內建 PHPUnit 支援,且 Laravel 還隨附了一個已設定好可在專案內使用的 phpunit.xml 。在 Laravel 中,也有許多方便的輔助函式,能讓我們精準地對專案進行測試。

預設情況下,專案的 tests 目錄內包含了兩個目錄:FeatureUnitUnit Test(單元測試) 是專注於測試一些小部分、與其他部分獨立的程式碼。其實,單元測試可能會只專注於測試單一方法。在「Unit」測試目錄下的測試不會啟用 Laravel 專案,因此無法存取專案的資料庫或其他 Laravel 的服務。

Feature Test(功能測試)可用來測試較大部分的程式碼 —— 測試各個物件要如何互相使用、測試 JSON Endpoint 的完整 HTTP Request 等。一般來說,大多數的測試應該都是 Feature Test。使用 Feature Test 有助於確保整體系統如期運作。

FeatureUnit 測試目錄下都有提供了一個 ExampleTest.php 檔。安裝好新的 Laravel 專案後,執行 vendor/bin/phpunitphp artisan test 指令即可執行測試。

環境

執行測試時,Laravel 會自動依照 phpunit.xml 檔內定義的環境變數來將設定環境設為 testing。在測試期間,Laravel 也會自動將 Session 與 Cache 設為 array Driver,以不保存測試期間的 Session 或 Cache 資料。

若有需要,也可以自行定義其他的測試環境設定值。testing 環境變數可以在專案的 phpunit.xml 檔案中修改。不過,在執行測試前,請記得使用 config:clear Artisan 指令來清除設定快取!

.env.testing 環境檔

除此之外,也可以也可以在專案根目錄上建立一個 .env.testing 檔案。在執行 PHPUnit 測試或使用 --env=testing 選項執行 Artisan 指令時,會使用這個檔案來代替 .env 檔案。

CreatesApplication Trait

Laravel 中包含了一個 CreatesApplication Trait。在專案的基礎 TestCase 類別中有套用這個 Trait。CreatesApplication 裡包含了一個 createApplication 方法,用來在執行測試前啟動 Laravel 程式。需注意要將該 Trait 保留在原位,因為某些 Laravel 的功能 —— 如平行測試 —— 需要仰賴於該 Trait。

建立測試

若要建立新測試例,請使用 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

若要建立 Pest PHP 測試,可在 make:test 指令上使用 --pest 選項:

1php artisan make:test UserTest --pest
2php artisan make:test UserTest --unit --pest
1php artisan make:test UserTest --pest
2php artisan make:test UserTest --unit --pest
lightbulb

可以安裝 Stub 來自訂測試的 Stub。

產生好測試後,即可如平常使用 PHPUnit 一般來定義測試方法。若要執行測試,請在終端機內執行 vendor/bin/phpunitphp artisan test 指令:

1<?php
2 
3namespace Tests\Unit;
4 
5use PHPUnit\Framework\TestCase;
6 
7class ExampleTest extends TestCase
8{
9 /**
10 * A basic test example.
11 *
12 * @return void
13 */
14 public function test_basic_test()
15 {
16 $this->assertTrue(true);
17 }
18}
1<?php
2 
3namespace Tests\Unit;
4 
5use PHPUnit\Framework\TestCase;
6 
7class ExampleTest extends TestCase
8{
9 /**
10 * A basic test example.
11 *
12 * @return void
13 */
14 public function test_basic_test()
15 {
16 $this->assertTrue(true);
17 }
18}
exclamation

若有自行在測試類別內定義 setUp / tearDown 方法,請記得呼叫上層類別內對應的 parent::setUp() / parent::tearDown() 方法。

執行測試

就像剛才提到的,寫好測試後,可使用 phpunit 來執行測試:

1./vendor/bin/phpunit
1./vendor/bin/phpunit

除了 phpunit 指令外,我們也可以使用 test Artisan 指令來執行測試。Artisan 的測試執行程式會提供較多輸出的測試報告,以讓我們能更輕鬆地進行開發與偵錯:

1php artisan test
1php artisan test

所有可傳給 phpunit 指令的引數都可傳給 Artisan test 指令:

1php artisan test --testsuite=Feature --stop-on-failure
1php artisan test --testsuite=Feature --stop-on-failure

平行執行測試

預設情況下,Laravel 與 PHPUnit 會依照順序在單一處理程序內執行我們的測試。不過,我們也可以同時以多個處理程序來執行測試,以大幅降低執行測試所需的時間。若要以多個處理程序執行測試,請先檢查專案是否有使用 ^5.3 或更新版的 nunomaduro/collision 套件。接著,請在執行 test Artisan 指令時使用 --parallel 選項:

1php artisan test --parallel
1php artisan test --parallel

預設情況下,Laravel 會以機器上可用的 CPU 核心數來建立處理程序。不過,我們也可以使用 --processes 選項來調整處理程序的數量:

1php artisan test --parallel --processes=4
1php artisan test --parallel --processes=4
exclamation

平行執行測試時,可能無法使用部分 PHPUnit 的選項 (如 --do-not-cache-result)。

平行測試與資料庫

只要你有設定主要的資料庫連線,Laravel 就會自動為每個執行測試的平行處理程序建立並 Migrate 測試資料庫。Laravel 會使用每個處理程序都不同的處理程序 Token 來作為資料庫的前置詞。舉例來說,若有兩個平行的測試處理程序,則 Laravel 會建立並使用 your_db_test_1your_db_test_2 測試資料庫。

預設情況下,在不同的 test Artisan 指令間,會共用相同的測試資料庫,以在連續呼叫 test 指令時使用這些資料庫。不過,我們也可以使用 --create-databases 選項來重新建立測試資料庫:

1php artisan test --parallel --recreate-databases
1php artisan test --parallel --recreate-databases

平行測試的 Hook

有時候,我們會需要為一些專案所使用的特定資源做準備,好讓我們能在多個測試處理程序中使用這些資源。

只要使用 ParallelTesting Facade,就可指定要在處理程序或測試例的 setUptearDown 內要執行的特定程式碼。給定的閉包會收到 $token$testCase 變數,著兩個變數中分別包含了處理程序的 Token,以及目前的測試例:

1<?php
2 
3namespace App\Providers;
4 
5use Illuminate\Support\Facades\Artisan;
6use Illuminate\Support\Facades\ParallelTesting;
7use Illuminate\Support\ServiceProvider;
8 
9class AppServiceProvider extends ServiceProvider
10{
11 /**
12 * Bootstrap any application services.
13 *
14 * @return void
15 */
16 public function boot()
17 {
18 ParallelTesting::setUpProcess(function ($token) {
19 // ...
20 });
21 
22 ParallelTesting::setUpTestCase(function ($token, $testCase) {
23 // ...
24 });
25 
26 // Executed when a test database is created...
27 ParallelTesting::setUpTestDatabase(function ($database, $token) {
28 Artisan::call('db:seed');
29 });
30 
31 ParallelTesting::tearDownTestCase(function ($token, $testCase) {
32 // ...
33 });
34 
35 ParallelTesting::tearDownProcess(function ($token) {
36 // ...
37 });
38 }
39}
1<?php
2 
3namespace App\Providers;
4 
5use Illuminate\Support\Facades\Artisan;
6use Illuminate\Support\Facades\ParallelTesting;
7use Illuminate\Support\ServiceProvider;
8 
9class AppServiceProvider extends ServiceProvider
10{
11 /**
12 * Bootstrap any application services.
13 *
14 * @return void
15 */
16 public function boot()
17 {
18 ParallelTesting::setUpProcess(function ($token) {
19 // ...
20 });
21 
22 ParallelTesting::setUpTestCase(function ($token, $testCase) {
23 // ...
24 });
25 
26 // Executed when a test database is created...
27 ParallelTesting::setUpTestDatabase(function ($database, $token) {
28 Artisan::call('db:seed');
29 });
30 
31 ParallelTesting::tearDownTestCase(function ($token, $testCase) {
32 // ...
33 });
34 
35 ParallelTesting::tearDownProcess(function ($token) {
36 // ...
37 });
38 }
39}

存取平行測試的 Token

若想從測試程式碼中的任何地方存取目前平行處理程序的「Token」,我們可以使用 token 方法。對於各個測試處理程序來說,平行處理程序的「Token」是一個不重複的字串,可用來在多個平行測試處理程序上為資源分段。舉例來說,Laravel 會自動將該 Token 放在各個由平行測試處理程序所建立的測試資料庫名稱後方:

1$token = ParallelTesting::token();
1$token = ParallelTesting::token();

回報測試覆蓋率

exclamation

要使用該功能,需安裝 XdebugPCOV

在執行專案測試時,我們可能會想判斷測試例是否有實際涵蓋到專案的程式碼、或是想知道在執行測試時到底使用到專案中多少的程式碼。若要瞭解測試覆蓋率,可在叫用 test 指令時提供 --coverage 選項:

1php artisan test --coverage
1php artisan test --coverage

強制最低覆蓋率門檻

可使用 --min 選項來為專案定義最低測試覆蓋率門檻。若未符合該門檻,測試套件會執行失敗:

1php artisan test --coverage --min=80.3
1php artisan test --coverage --min=80.3
翻譯進度
100% 已翻譯
更新時間:
2023年2月11日 下午12:59:00 [世界標準時間]
翻譯人員:
  • cornch
幫我們翻譯此頁

留言

尚無留言

“Laravel” is a Trademark of Taylor Otwell.
The source documentation is released under MIT license. See laravel/docs on GitHub for details.
The translated documentations are released under MIT license. See cornch/laravel-docs-l10n on GitHub for details.