测试方法
标记分组 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);
});
});