关于 speeding-up-laravel-tests
面向 Laravel 开发者的测试提速清单,涵盖环境配置、外部交互模拟、数据库开销和性能分析,并优先列出低成本的环境调整。
主要功能
- 01调整测试环境配置
- 02模拟外部交互
- 03降低数据库准备开销
- 04分析慢速测试
适用场景
- 01缩短耗时较长的 CI 测试
- 02排查单个慢速测试
- 03为新项目建立测试检查清单
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ freekmurze/ dotfiles --skill speeding-up-laravel-tests安装后在 Claude Code 中输入/speeding-up-laravel-tests确认已加载。
详细介绍
加快 Laravel 测试
精选的 Laravel 测试套件提速技巧。建议大致按以下顺序应用;修复环境通常能以最少的工作带来最大的收益。
适用场景
- 测试套件平均每个测试耗时超过几秒。
- CI 耗时不断增加,你希望缩短几分钟。
- 某个特定测试运行缓慢,你想检查它实际在做什么。
- 你正在接手一个新项目,想要一份标准检查清单。
环境和配置
- 在
.env.testing(或phpunit.xml)中设置BCRYPT_ROUNDS=4。 默认值为 12,而哈希计算会显著拖慢身份验证测试。 - 禁用 XDebug。 大规模测试时也禁用 pcov,除非你确实需要覆盖率。
- 在测试环境中禁用后台运行的包: Pulse、Telescope、Nightwatch 及其他类似的第三方包,这些包会在每次请求或命令中执行工作。
- 使用
WithCachedConfig和WithCachedRoutestrait,避免每次测试都重新解析配置和路由。 - 在测试设置中调用
withoutVite()(或withoutMix()), 避免框架尝试解析已构建的资源。
模拟外部交互
任何与非测试目标外部服务的交互都应进行模拟。
Notification::fake()、Mail::fake()、Bus::fake()、Event::fake()、Queue::fake()。- 会分发任务的 HTTP 端点: 除非测试要断言任务行为,否则应模拟队列。否则任务会以内联方式执行,并引入它们涉及的所有内容。
- 事件监听器: 如果不相关的监听器被触发并执行工作,就对它们使用
Event::fake()。利用 Laravel 的事件系统,查明慢速测试期间触发了哪些事件。 - 在测试套件中使用
Http::preventingStrayRequests()。 一个缓慢的意外请求就可能拖慢每个测试。请注意,这只能捕获通过 Laravel HTTP 客户端发出的请求。请另行检查直接使用 Guzzle / cURL 的情况。 - 使用
Sleep::fake(syncWithCarbon: true), 避免重试和退避逻辑真的休眠。要求代码使用Sleep助手,而不是 PHP 的sleep()。 - 使用
Exceptions::fake(), 确保测试中不会向 Flare/Sentry/Bugsnag 报告异常。
数据库
- 用
LazilyRefreshDatabase替代RefreshDatabase。 从未访问数据库的测试可以完全跳过迁移和截断的开销。 - 检查工厂的使用情况。 工厂是常见的性能热点,因为很容易创建出超出测试所需的模型。留意嵌套的
create()调用是否生成了额外记录。 - 使用
$factory->recycle($model)创建一个共享的父模型,并将其传递给嵌套的工厂调用,而不是让每个嵌套工厂都创建自己的父模型。
性能分析与诊断
./vendor/bin/pest --profile会列出每个分片中最慢的测试。从这里开始排查。耗时最长的 10 个测试中发现的模式往往也适用于整个测试套件。- 使用 https://marmelab.com/phpunit-d3-report/ 可视化测试套件(最初面向 PHPUnit;请确认与 Pest 兼容)。
- 如果某个测试为何缓慢难以查明,可以检测事件监听器或添加临时日志,找出幕后发生的意外工作。
快速参考
| 区域 | 操作 |
|---|---|
| 哈希计算 | BCRYPT_ROUNDS=4 |
| 调试器 | 禁用 XDebug,禁用 pcov |
| 后台包 | 禁用 Pulse、Telescope、Nightwatch |
| 配置 / 路由 | WithCachedConfig、WithCachedRoutes |
| 资源 | withoutVite() / withoutMix() |
| 外部服务 | Notification::fake()、Mail::fake()、Bus::fake()、Event::fake()、Queue::fake() |
| HTTP | Http::preventingStrayRequests() |
| 休眠 | Sleep::fake(syncWithCarbon: true) |
| 异常 | Exceptions::fake() |
| 数据库 | LazilyRefreshDatabase |
| 工厂 | $factory->recycle($model),检查嵌套的创建操作 |
| 性能分析 | pest --profile |
常见错误
- 即使测试不会访问数据库,也在每个测试中启用
RefreshDatabase。 - 在生产代码中调用真实的
sleep()或使用 Carbon,导致Sleep::fake()无法发挥作用。 - 添加
Queue::fake(),却仍然断言作业的副作用(这些副作用永远不会发生)。 - 为了以防测试失败,运行测试套件时加载 XDebug。
- 因为从未创建
.env.testing,而让BCRYPT_ROUNDS保持默认值。
评论
支持 Markdown