戏里戏外

FilamentPHP 资源测试实战

2025-04-25#Filament

在现代 PHP 后台开发中,自动化测试已成为保障项目质量的重要手段。

FilamentPHP 作为一款流行的 Laravel 后台管理面板,提供了丰富的资源(Resource)和页面(Page)管理能力。

测试环境准备

首先,确保已经安装并配置好 FilamentPHP 及其依赖,并为 Company 资源生成了对应的 Resource 和 Page。

基础页面渲染测试

需要确保资源的各个页面都能正常渲染:

it('can render the index page', function () {
    livewire(ListCompanies::class)
        ->assertOk();
});

it('can render the create page', function () {
    livewire(CreateCompany::class)
        ->assertOk();
});

it('can render the edit page', function () {
    $record = Company::factory()->create();
    livewire(EditCompany::class, ['record' => $record->getRouteKey()])
        ->assertOk();
});

表格列的存在性与渲染

确保表格包含并能正确渲染所有关键字段:

it('has column', function (string $column) {
    livewire(ListCompanies::class)
        ->assertTableColumnExists($column);
})->with(['name', 'email', 'phone', 'status', 'created_at', 'updated_at']);

it('can render column', function (string $column) {
    livewire(ListCompanies::class)
        ->assertCanRenderTableColumn($column);
})->with(['name', 'email', 'phone', 'status', 'created_at', 'updated_at']);

排序与搜索功能测试

验证表格的排序和搜索功能:

it('can sort column', function (string $column) {
    $records = Company::factory(5)->create();
    livewire(ListCompanies::class)
        ->sortTable($column)
        ->assertCanSeeTableRecords($records->sortBy($column), inOrder: true)
        ->sortTable($column, 'desc')
        ->assertCanSeeTableRecords($records->sortByDesc($column), inOrder: true);
})->with(['name', 'status', 'created_at', 'updated_at']);

it('can search column', function (string $column) {
    $records = Company::factory(5)->create();
    $search = data_get($records->first(), $column);
    livewire(ListCompanies::class)
        ->searchTable($search instanceof BackedEnum ? $search->value : $search)
        ->assertCanSeeTableRecords($records->filter(fn (Company $record) => data_get($record, $column) == $search));
})->with(['name', 'email', 'phone']);

增删改查(CRUD)操作测试

创建公司

it('can create a company', function () {
    $record = Company::factory()->make();
    livewire(CreateCompany::class)
        ->fillForm([
            'name' => $record->name,
            'email' => $record->email,
            'phone' => $record->phone,
            'status' => $record->status,
        ])
        ->assertActionExists('create')
        ->call('create')
        ->assertHasNoFormErrors();

    $this->assertDatabaseHas(Company::class, [
        'name' => $record->name,
        'email' => $record->email,
    ]);
});

更新公司


it('can update a company', function () {
    $record = Company::factory()->create();
    $newRecord = Company::factory()->make();
    livewire(EditCompany::class, ['record' => $record->getRouteKey()])
        ->fillForm([
            'name' => $newRecord->name,
            'email' => $newRecord->email,
            'phone' => $newRecord->phone,
            'status' => $newRecord->status,
        ])
        ->assertActionExists('save')
        ->call('save')
        ->assertHasNoFormErrors();

    $this->assertDatabaseHas(Company::class, [
        'name' => $newRecord->name,
        'email' => $newRecord->email,
        'phone' => $newRecord->phone,
        'status' => $newRecord->status,
    ]);
});

删除公司

it('can delete a company', function () {
    $record = Company::factory()->create();
    livewire(EditCompany::class, ['record' => $record->getRouteKey()])
        ->assertActionExists('delete')
        ->callAction(DeleteAction::class);

    $this->assertModelMissing($record);
});

批量删除

it('can bulk delete companies', function () {
    $records = Company::factory(5)->create();
    livewire(ListCompanies::class)
        ->assertTableBulkActionExists('delete')
        ->callTableBulkAction(DeleteBulkAction::class, $records);

    foreach ($records as $record) {
        $this->assertModelMissing($record);
    }
});

表单校验测试

包括必填、邮箱格式、最大长度、枚举值等校验:

it('can validate required', function (string $column) {
    livewire(CreateCompany::class)
        ->fillForm([$column => null])
        ->assertActionExists('create')
        ->call('create')
        ->assertHasFormErrors([$column => ['required']]);
})->with(['name', 'email', 'status']);

it('can validate email', function (string $column) {
    livewire(CreateCompany::class)
        ->fillForm(['email' => Str::random()])
        ->assertActionExists('create')
        ->call('create')
        ->assertHasFormErrors([$column => ['email']]);
})->with(['email']);

it('can validate max length', function (string $column) {
    livewire(CreateCompany::class)
        ->fillForm([$column => Str::random(256)])
        ->assertActionExists('create')
        ->call('create')
        ->assertHasFormErrors([$column => ['max:255']]);
})->with(['name', 'email', 'phone']);

it('can validate status enum', function () {
    $record = Company::factory()->make();
    livewire(CreateCompany::class)
        ->fillForm([
            'name' => $record->name,
            'email' => $record->email,
            'phone' => $record->phone,
            'status' => 'invalid-status',
        ])
        ->assertActionExists('create')
        ->call('create')
        ->assertHasFormErrors([
            'status' => ['Illuminate\\Validation\\Rules\\Enum'],
        ]);
});

通过上述测试用例,可以全面覆盖 FilamentPHP 资源的各项功能,确保后台管理系统的稳定性和可靠性。

建议在实际开发中根据业务需求灵活调整和补充测试内容。

参考:完整测试代码 Gist

如需进一步了解 FilamentPHP 测试实践,可以访问官方文档