laravel测试慢的主因是默认配置不当:应改用内存sqlite(db_database=:memory:)、禁用冗余服务提供者、用assertsame替代assertequals、并行执行paratest。关键验证数据库是否真走内存。

直接跑 phpunit 太慢?不是代码问题,而是默认配置和执行方式没调对。Laravel 测试套件本身不慢,慢在 SQLite 文件磁盘 I/O、重复启动应用、低效断言和单核串行执行。
用内存 SQLite 替代文件 SQLite
Laravel 默认的 testing 环境虽然配了 sqlite,但很多人没改 database.sqlite 路径,导致每次测试都读写磁盘文件。真正的加速起点是强制走内存数据库。
- 在
phpunit.xml的<php></php>段里加环境变量:DB_DATABASE=:memory: - 确保
config/database.php中sqlite配置的database键值能被该变量覆盖(不要硬编码路径) - 移除
database_path('database.sqlite')这类写死路径,否则内存模式不生效
禁用不必要的服务提供者
Tests\TestCase 每次运行都会完整启动 Laravel 应用容器,加载全部 providers。单元测试根本不需要 Mail、Queue、Redis 等服务,它们只会拖慢启动速度。
- 在
tests/TestCase.php的createApplication()方法中,覆盖$app->registerProviders([])并手动注册最小集 - 或使用
withoutEvents()、withoutJobs()、withoutNotifications()等内置方法,在测试方法开头调用 - 注意:Feature 测试若依赖中间件或认证逻辑,需保留
AppServiceProvider和AuthServiceProvider,不能全关
换用 assertSame 替代 assertEquals
当断言简单类型(字符串、数字、布尔)时,assertEquals 会尝试递归对比并生成详细 diff,开销显著。而 assertSame 直接用 === 判断,快一个数量级。
- 把
$this->assertEquals('ok', $response['status'])改成$this->assertSame('ok', $response['status']) - 仅在需要查看结构差异时(如数组嵌套深度大、调试失败用例)才用
assertEquals - 对数据库断言如
assertDatabaseHas不受影响,它底层不走 PHPUnit 断言链
并行执行测试用 paratest
单核跑 200 个测试要 12 秒,4 核并行通常压到 3–4 秒内。关键是避免共享状态——Laravel 测试默认用内存数据库,天然适合并行。
- 安装:
composer require --dev brianium/paratest - 运行:
vendor/bin/paratest --phpunit vendor/bin/phpunit --processes=4 - 必须加
--no-coverage参数,否则覆盖率收集会竞争写文件导致崩溃 - 如果测试里用了
file_put_contents或临时目录,需改用sys_get_temp_dir()+ 唯一前缀,否则冲突
最常被忽略的是内存数据库配置是否真正生效——很多项目只改了 .env.testing,却没在 phpunit.xml 中显式注入 DB_DATABASE=:memory:,结果还是在刷磁盘。跑完 phpunit --debug 看第一条测试的数据库连接日志,确认 host 是 :memory: 而不是某个 .sqlite 文件路径,才算调对了。











