測試方法
標記分組 group()
特定測試標記分組
./vendor/bin/pest --group=integration
it('has home', function () {
// 測試內容
})->group('integration');
./vendor/bin/pest --group=feature
it('has home', function () {
// 測試內容
})->group('feature', 'browser');
整個描述區塊標記分組
describe('home', function () {
test('main page', function () {
// 測試內容
});
})->group('feature');
在測試文件中標記整個文件為某個分組
// tests/Feature/HomeTest.php
pest()->group('feature');
it('has home', function () {
// 測試內容
});
依賴測試 depends()
這使得某個測試(子測試)可以依賴於其他測試(父測試)的結果,從而確保只有在父測試成功的情況下,子測試才會被執行。
注意事項
項目 | 說明 |
---|---|
依賴性不常見 | 雖然設置測試依賴性是可行的,但通常不建議過度使用。過多的依賴性可能會使測試變得難以維護和理解。 |
清晰的錯誤消息 | 如果任何父測試失敗,Pest 會顯示清晰的錯誤消息,告訴您哪個父測試導致了子測試的跳過。 |
單一依賴
test('parent', function () {
return 'from parent';
});
test('child', function ($parentValue) {
expect($parentValue)->toBe('from parent');
})->depends('parent');
多重依賴
test('a', function () {
return 'a';
});
test('b', function () {
return 'b';
});
test('c', function () {
return 'c';
});
test('d', function ($testA, $testB, $testC) {
expect($testA)->toBe('a');
expect($testB)->toBe('b');
expect($testC)->toBe('c');
})->depends('a', 'b', 'c');
僅運行特定的測試 only()
it('returns a successful response', function () {
$response = $this->get('/');
$response->assertStatus(200);
})->only();
<!--adsense-->
### 跳過不必要的測試 skip()
```php
it('has home', function () {
// 測試內容
})->skip('This test is not needed anymore);
在每個測試之前執行代碼 beforeEach()
項目 | 說明 |
---|---|
執行時機 | 在每個測試之前執行。 |
範圍 | 每次測試都會觸發這個方法,這意味著如果您有多個測試,beforeEach 將在每個測試之前執行一次。 |
用途 | 通常用來設置每個測試所需的環境或狀態,例如初始化變數、創建測試資料等。 |
beforeEach(function () {
// 在每個測試之前執行的代碼
});
所有測試之前只會執行一次 beforeAll()
項目 | 說明 |
---|---|
執行時機 | 在所有測試之前僅執行一次。 |
範圍 | 這個鉤子只會在整個檔案中的所有測試運行之前執行一次,因此它適合用於全局的初始化工作。 |
用途 | 通常用來進行一次性的設置,例如配置資料庫連接、載入設定檔等。 |
beforeAll(function () {
// 所有測試之前只會執行一次
$this->sharedData = SomeSharedResource::initialize();
});
it('uses shared data', function () {
expect($this->sharedData)->toBeNotNull();
});
it('can access shared data again', function () {
expect($this->sharedData)->toHaveProperty('key');
});
### 測試資料集 dataset()
```php
// tests/Feature/Products/ExampleTest.php...
it('has products', function (string $product) {
expect($product)->not->toBeEmpty();
})->with('products');
// tests/Feature/Products/Datasets.php...
dataset('products', [
'egg',
'milk'
]);
重複測試 repeat()
it('can repeat a test', function () {
$result = /** Some code that may be unstable */;
expect($result)->toBeTrue();
})->repeat(100); // Repeat the test 100 times
定義共享方法
您可以在 tests/Pest.php
中定義一個 login() 方法來模擬用戶登入:
// tests/Pest.php
use App\Models\User;
function login($user = null) {
return test()->actingAs($user ?? User::factory()->create());
}
使用測試方法 uses()
Database Testing - Laravel 11.x - The PHP Framework For Web Artisans
項目 | 方法 | 說明 |
---|---|---|
交易測試 | uses(DatabaseTransactions::class); |
交易測試,測試完成後會自動回滾。 |
重設資料庫 | uses(RefreshDatabase::class); |
重設資料庫,每個測試完成後會自動重設資料庫。 |
延遲重設資料庫 | uses(LazilyRefreshDatabase::class); |
只有在測試過程中實際進行資料庫操作時才會刷新資料庫,這樣可以避免不必要的資料庫重置,從而提高測試速度。 |
uses(\Illuminate\Foundation\Testing\DatabaseTransactions::class);
uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);
uses(\Illuminate\Foundation\Testing\LazilyRefreshDatabase::class);
過濾測試 Filtering Tests
參數 | 說明 | 指令 |
---|---|---|
–bail | 當遇到第一個失敗或錯誤時停止執行測試。 | ./vendor/bin/pest --bail |
–dirty | 僅運行有未提交變更的測試,適合在開發新功能時使用。 | ./vendor/bin/pest --dirty |
–filter | 根據指定的正則表達式過濾並運行測試,這可以是測試名稱、描述或其他相關信息。 | ./vendor/bin/pest --filter="it should perform a specific action" |
–group | 運行屬於特定群組的測試。可以使用 group() 函數將測試分組。 |
./vendor/bin/pest --group=integration |
–exclude-group | 排除特定群組的測試不被執行。 | ./vendor/bin/pest --exclude-group=slow |
–retry | 優先運行之前失敗的測試,這樣可以更快地檢查修復是否有效。 | ./vendor/bin/pest --retry |
–parallel | 並行執行測試 | ./vendor/bin/pest --parallel |
繼承測試類別 Extend Test Class
Configuring Tests | Pest - The elegant PHP Testing Framework
pest()->extend(Tests\TestCase::class)->in('Feature');
將 Tests\TestCase
類別繼承到 pest()
函數中,並套用目錄所有的測試檔案。
指令 | 套用目錄 |
---|---|
pest()->extend()->in('Feature'); |
tests/Feature |
pest()->extend()->in('Scenario'); |
tests/Scenario |
pest()->extend()->in('Feature/*Job*.php'); |
tests/Feature 目錄下所有有 Job 檔名的測試檔案 |
pest()->extend()->in(['Feature', 'Scenario']); |
tests/Feature 和 tests/Scenario |
pest()->extend()->in('../app/test'); |
app/test |
pest()->extend()->in('../app/test/*'); |
app/test/* |
describe 與 it 的差異是什麼?
it
的功能
項目 | 說明 |
---|---|
定義單一測試 | it 用來定義一個具體的測試案例。每個 it 測試都應該檢查一個特定的行為或結果。 |
描述性 | 與 describe 一樣,it 也接受一個字符串作為描述,這個描述應該清楚地表達出該測試所檢查的內容。 |
例如:
it('returns a successful response', function () {
// 測試邏輯
});
describe
的功能
項目 | 說明 |
---|---|
用於組織測試 | describe 用來定義一組相關的測試,通常是針對同一個功能或模組的測試。它可以幫助您將測試分組,使測試結果更具可讀性。 |
描述性 | describe 接受一個字符串作為描述,這個描述通常是您正在測試的功能或模組的名稱,並且可以包含多個 it 測試。 |
例如:
describe('User Registration', function () {
it('registers a user successfully', function () {
// 測試邏輯
});
it('fails when email is already taken', function () {
// 測試邏輯
});
});
在這個例子中,所有與用戶註冊相關的測試都被組織在一起,這樣可以清晰地顯示出這些測試的上下文。
這裡的 it
測試檢查某個操作是否返回成功的響應。
總結
項目 | 說明 |
---|---|
結構化 | 使用 describe 可以將相關的測試分組,而 it 則用於具體的測試案例。這種結構化使得測試代碼更加清晰和易於維護。 |
可讀性 | 這種方式不僅提高了代碼的可讀性,也使得測試報告更具可理解性,因為它清楚地顯示了哪些功能被測試以及每個功能下有多少個具體的測試案例。 |
test() 方法和 it() 方法是一樣的
可以自由選擇使用其中任何一個來撰寫測試。這兩者的功能和用法是一樣的,主要的區別在於語義和可讀性。
方法名稱 | 說明 |
---|---|
test() |
用於定義一個測試案例,接受一個描述和一個回調函數。這個方法的語法更接近於傳統的 PHPUnit 測試方法。 |
it() |
這是一個語義更強的方法,通常用於撰寫更自然的測試描述,例如 “it should do something”。這使得測試更加可讀。 |
使用 test()
test('sum of two numbers', function () {
$result = sum(1, 2);
expect($result)->toBe(3);
});
使用 it()
it('calculates the sum of two numbers', function () {
$result = sum(1, 2);
expect($result)->toBe(3);
});
語義上的差異
項目 | 說明 |
---|---|
可讀性 | it() 方法提供了一種更自然的語言結構,使得測試描述更易於理解。例如,it('calculates the sum of two numbers') 讓人感覺像是在描述一個行為,而不是僅僅在陳述一個事實。 |
一致性 | 使用 describe() 結合 it() 可以讓測試組織得更加清晰。 |
describe('Sum Function', function () {
it('calculates the sum of two integers', function () {
$result = sum(1, 2);
expect($result)->toBe(3);
});
it('calculates the sum of two floats', function () {
$result = sum(1.5, 2.5);
expect($result)->toBe(4.0);
});
});