Laravel 10+ 原生并行测试更可靠,因其深度集成:自动分配独立数据库、协同测试工具链;而 para-test 作为通用并行器,无法安全处理 Laravel 特有机制。

Laravel 10+ 原生支持并行测试,无需额外安装 para-test;强行集成反而会引发进程冲突、数据库隔离失败和测试状态污染。
为什么 Laravel 自带的 php artisan test --parallel 比 para-test 更可靠
Laravel 的并行测试是深度集成的:它自动为每个 worker 分配独立的 DB_DATABASE(如 testing_1, testing_2),复用 DatabaseMigrations 或 RefreshDatabase 的事务/重置逻辑,并与 TestResponse、Http::fake() 等测试工具链协同工作。而 para-test 是通用 PHP 测试并行器,不理解 Laravel 的应用上下文,无法安全处理:
-
Illuminate\Foundation\Testing\RefreshDatabase的数据库重置时机 -
app()->flush()和服务容器重建边界 -
Queue::fake()或Notification::fake()的单例作用域
启用 Laravel 并行测试的正确方式
确保满足以下前提,再直接运行命令:
- Laravel ≥ 10.0(Laravel 9 需手动升级
laravel/pint和pestphp/pest才能有限支持) - PHP ≥ 8.1(依赖
ext-pcntl和ext-posix) -
phpunit.xml中未覆盖processIsolation="true"(这会禁用 Laravel 的并行机制) - 所有测试类继承
Tests\TestCase,且未在setUp()中执行全局副作用(如修改$_SERVER、写文件)
直接运行:
php artisan test --parallel
可选参数:
-
--workers=4:显式指定进程数(默认为 CPU 核心数 − 1) -
--rebuild:每次 worker 启动前重新启动 Laravel 应用实例(解决某些静态状态残留) -
--without-tty:CI 环境下避免 ANSI 控制字符干扰日志
常见失败场景与修复
并行测试失败往往不是因为“不能并行”,而是测试本身存在隐式共享状态:
-
数据库表名硬编码:避免在测试中写
DB::table('users'),改用模型User::factory()->create(),确保走的是当前 worker 的隔离库 -
缓存未清空:Laravel 并行不自动清
cache:clear,若测试中用了Cache::put('key', 'val'),需在tearDown()显式调用Cache::flush() -
自定义 Artisan 命令未重置状态:若测试中调用
Artisan::call('foo:bar'),该命令内部若缓存了静态属性,需在命令类中实现__destruct()或使用app()->forgetInstance() -
文件系统写入冲突:避免测试中写
storage_path('app/test.txt'),改用tempnam(sys_get_temp_dir(), 'test_')
CI 环境适配要点
GitHub Actions / GitLab CI 中需显式启用扩展并限制 workers:
php: - 8.2services:
- mysql:8.0
env: DB_CONNECTION: mysql DB_HOST: mysql DB_PORT: 3306 DB_DATABASE: testing DB_USERNAME: root DB_PASSWORD: password
script:
- composer install
- php artisan test --parallel --workers=2 --without-tty
关键点:
- MySQL 服务必须支持并发连接(默认 151 足够,但若 workers > 10,需调大
max_connections) - 不要在 CI 中用
sqlite:memory:—— 它无法跨进程共享,Laravel 并行会为每个 worker 创建新内存库,导致迁移失败 - 若用 PostgreSQL,确保
PGDATABASE不被硬编码,Laravel 会自动追加后缀生成独立库名
并行测试真正的门槛不在配置,而在测试是否真正无状态。一个
static $loaded = false;在测试辅助类里,就足以让所有 worker 相互干扰 —— 这类问题不会报错,只会让断言偶尔失败,最难排查。 - MySQL 服务必须支持并发连接(默认 151 足够,但若 workers > 10,需调大










