编程

Pest 架构测试插件

857 2023-05-14 23:06:00

随着 PestPHP v2 的发布,现在我们可以测试应用的架构了。本教程将介绍如何使用这一插件。

首先在应用的 tests/Feature 目录下创建一个 ArchTest.php 文件。从这里开始,我们可以开始记录我们的架构需求和规则,使我们能够用出色的 API 和出色的开发体验来测试这些需求和规则。

我推荐你添加的一个测试,确保应用中不会留下 debug 的调用。

test('Not debugging statements are left in our code.')
 ->expect(['dd', 'dump', 'ray'])
 ->not->toBeUsed();

在我们深入研究我们可以使用的可用规则之前,让我们分析一下这些测试的结构。它从一个 test调用开始,在这里我们定义了测试的名称——确保这是可以理解的,描述了您正在测试的内容。然后,我们使用 Pest 高阶期望 API 来声明我们正在测试的内容。我们从期待(expect)开始。在上述情况下,我们期望不会使用以下内容,或者我们可能会出现一些内容。

接下来,让我们看看我们可以创建的更具体的测试,以确保我们的架构规则得到遵守。显然,我们需要做的第一件事是确保我们了解我们的架构实践是什么。你不能简单地执行你不打算遵守的规则。在本教程中,我将记录一些我喜欢应用于我的项目的规则。作为一个没有主见的开发人员。

test('Our API controllers return responses that we expect')
    ->expect('Illuminate\Contracts\Support\Http\Responsable')
    ->toBeUsedIn('App\Http\Controllers\Api');

在这个测试中,我们希望确保在 API 中使用响应类。我们的控制器应该返回 Responsable 类,这样我们就可以最大限度地减少代码重复,并始终以标准方式返回。

test('We do not directly use Eloquent Models in our APIs.')
    ->expect('App\Models')
    ->not->toBeUsedIn('App\Http\Controllers\Api');

在这个测试中,我们希望确保我们不会在 API 中直接使用 Eloquent 模型。在使用数据库时,我们应该使用 Action、Command、Query 或 Service/Repository 类。这是我喜欢尽可能遵循的规则,因为它可以减少代码重复。

test('We always use Resouce classes when responding')
    ->expect('App\Http\Resources')
    ->toBeUsedIn('App\Http\Controllers\Api');

在这个测试中,我们希望确保始终在控制器中使用 Resource 类。这使我们能够确保我们有一种标准化的方式来从 API 返回数据。

以下规则将更具体地体现我的编码方式,因此它可能与你无关,但它显示了你可以测试代码的模块化方面的特定方法。

我在很大程度上依赖于 Laravel 的模块化方法,在需要的地方使用单独的命名空间。我还非常依赖于用于写入操作的命令和用于读取操作的查询。我可以确保在对我有意义的地方使用它们。

test('We use Query classes where we need them in the Catalog domain')
    ->expect('Domains\Catalog\Queries')
    ->toBeUsedIn('App\Http\Controllers\Api\V1\Products\Read');

在该架构插件支持通配符之前,这是我目前使用的临时措施。我们希望确保在正确的位置使用查询。一旦我们允许在架构插件中使用通配符,我们就可以这样做:

test('Query classes are used for read operations')
    ->expect('Domains\*\Queries')
    ->toBeUsedIn('App\Http\Controllers\Api\*\*\IndexController')
    ->toBeUsedIn('App\Http\Controllers\Api\*\*\ShowController')
    ->not->toBeUsedIn('App\Http\Controllers\Api\*\*\StoreController')
    ->not->toBeUsedIn('App\Http\Controllers\Api\*\*\UpdateController')
    ->not->toBeUsedIn('App\Http\Controllers\Api\*\*\DeleteController');

通过此测试,我们可以确保在所有读取端点中使用查询,但在写入端点中不使用查询,从而使我们能够更严格地控制代码体系结构和方法。

当然,这目前还不可用,但也许它将使我们在未来拥有更少的架构规则和相同的覆盖范围。