就上下文而言,我正在开发一个基于RNG的赛车运动模拟器,因为没有更好的术语。用户可以创建宇宙(想想现实生活中的FIA(,在宇宙中他们可以创建系列赛(想想F1、F2、F3等(,在每个系列赛中他们都可以创建赛季。在每个模型中,用户都可以创建额外的模型;
在一个宇宙中,用户可以创建团队和驱动程序。
在一个赛季中,用户可以使用他们在任何宇宙之外添加的赛道、参赛者(基于他们在母宇宙中创建的车队(创建日历,并可以向这些参赛者添加车手(基于创建的车手(,我称之为"车手";阵容";。
我对这些关系的测试越深入,就越需要通过工厂创建更多的模型来进行正确的测试,测试运行所需的时间也就越长。我有一个非常简单的测试来验证宇宙所有者是否可以为属于该宇宙的参与者添加驱动程序;
test('a universe owner can add drivers to entrants', function () {
$user = User::factory()->create();
$season = createSeasonForUser($user);
$driver = Driver::factory()->for($season->universe)->create();
$entrant = Entrant::factory()->for($season)->create();
$this->actingAs($user)
->post(route('seasons.lineups.store', [$season]), [
'driver_id' => $driver->id,
'entrant_id' => $entrant->id,
'number' => 2,
])
->assertRedirect(route('seasons.lineups.index', [$season]));
$this->assertDatabaseCount('lineups', 1);
$this->assertCount(1, $entrant->drivers);
$this->assertCount(1, $season->drivers);
});
我有两个助手功能,可以快速创建属于特定用户的系列和/或季节;
function createSeriesForUser(User $user): Series
{
return Series::factory()->for(Universe::factory()->for($user)->create())->create();
}
function createSeasonForUser(User $user): Season
{
$series = createSeriesForUser($user);
return Season::factory()->for($series)->create();
}
正如你所看到的,为了测试流程的一部分,我需要通过工厂创建六个模型(其中一些工厂有时会调用更多的工厂(。我运行了五次测试,对测试的每个部分(工厂、实际请求和断言(进行计时,工厂平均耗时1.9秒,其余测试耗时0015秒,这对我来说似乎不正确
理想情况下,我会在每个测试文件运行之前创建所有必需的数据库条目,但我知道这是一种糟糕的做法。有没有其他方法可以加快测试速度?遗憾的是,我无法让这些关系变得不那么嵌套或复杂,因为这些只是我正在构建的网站的要求。
或者,这种方法通常是测试控制器功能的正确方法吗?或者可以采取不同的方法吗?
为了不让问题太混乱,这里有一个粘贴箱,里面有目前所有的工厂
原来Faker的image()
真的很慢。我用'avatar' => null,
替换了UserFactory中的'avatar' => $this->faker->image(),
,现在我的整个测试服只运行了不到三秒,如果我并行运行,则只运行一秒钟。