大家的测试用例都是怎么写的?
之前在测试用例方面实践的太少,一开始是觉得会迟滞开发进度,但当项目逐渐复杂之后,测试的紧迫性就提上来了,但这个时候团队往往会路径依赖,很难再去花成本去补之前落下的功课。
现在来看,之后有可能会重新组队了,加之 AI 助手的协助降低了一些编码的成本。我还是想把测试抓起来,但又缺乏相关的经验,想征询一下大家的实践经验。
我用需求例子讲一下自己的问题:
分类管理功能简述:向前端提供一组接口实现对分类数据的增删改查。
那么如果要写一个用例是对接口测试还是对服务测试?还是说两者都需要?
我一般会将业务处理抽象出来封装成服务类,比如:
接口 POST /api/goods/categories
经由控制器方法 CategoryController::store()
调用服务方法 CategoryStoreService::handle()
其中 CategoryStoreService::handle()
方法是之后会被通过导入、ERP数据同步等功能复用的,那么对这个方法的测试就显得很重要。可能有以下用例:
test('分类存储 冒烟测试', function ($name) {
/** @var CategoryStoreService $service */
$service = app(CategoryStoreService::class);
$category = $service->handle($name);
expect($category->name)->toBe($name);
})->with([
'服装',
'鞋帽',
'家电',
]);
test('分类存储 恢复同名已删除', function () {
/** @var CategoryStoreService $service */
$service = app(CategoryStoreService::class);
$category = $service->handle('服装');
$id = $category->id;
$category->delete();
$category = $service->handle('服装');
expect($category->name)->toBe('服装');
expect($category->id)->toBe($id);
expect($category->trashed())->toBeFalse();
});
test('分类存储 验证测试 空名称', function ($name) {
/** @var CategoryStoreService $service */
$service = app(CategoryStoreService::class);
$service->handle($name);
})->with([
'',
])->throws(InvalidArgumentException::class, '分类名称不能为空');
test('分类存储 验证测试 名称过长', function () {
/** @var CategoryStoreService $service */
$service = app(CategoryStoreService::class);
$service->handle(str_repeat('a', 256));
})->throws(InvalidArgumentException::class, '分类名称不能超过 255 个字符');
test('分类存储 验证测试 重复名称', function () {
/** @var CategoryStoreService $service */
$service = app(CategoryStoreService::class);
$service->handle('服装');
$service->handle('服装');
})->throws(InvalidArgumentException::class, '分类名称已存在');
但对于前端团队来讲他们更关注与接口的交互,每次服务端的迭代是否对接口服务造成影响,可能有以下用例:
test('/api/goods/categories 存储后关键词检索', function (User $user) {
$responseStore = $this
->actingAs($user)
->postJson('/api/goods/categories', ['name' => '服装']);
$responseStore->assertStatus(201);
$responseIndex = $this->get('/api/goods/categories?keyword=服装');
$responseIndex->assertStatus(200);
$responseIndex->assertJsonCount(1, 'data');
})->with([
fn() => User::factory()->create(),
]);
test('/api/goods/categories 存储 空名称', function (User $user) {
$responseStore = $this
->actingAs($user)
->postJson('/api/goods/categories', ['name' => '']);
$responseStore->assertStatus(422);
$responseStore->assertJsonValidationErrors('name');
})->with([
fn() => User::factory()->create(),
]);
test('/api/goods/categories 存储 名称过长', function (User $user) {
$responseStore = $this
->actingAs($user)
->postJson('/api/goods/categories', ['name' => str_repeat('a', 256)]);
$responseStore->assertStatus(422);
$responseStore->assertJsonValidationErrors('name');
})->with([
fn() => User::factory()->create(),
]);
test('/api/goods/categories 存储 重复名称', function (User $user) {
$responseStore = $this
->actingAs($user)
->postJson('/api/goods/categories', ['name' => '服装']);
$responseStore->assertStatus(201);
$responseDuplicate = $this
->actingAs($user)
->postJson('/api/goods/categories', ['name' => '服装']);
$responseDuplicate->assertStatus(422);
$responseDuplicate->assertJson(['message' => '分类名称已存在']);
})->with([
fn() => User::factory()->create(),
]);
至少从目前的用例上看,对服务的测试逻辑基本上等效于对接口的测试。那么我的问题是:如果让大家来写,两套用例是否都有必要?还是说只保留其中一套即可?
推荐文章: