test脚本需在composer.json的scripts中手动定义,推荐写法为"test": "vendor/bin/phpunit --colors=always",优先使用vendor内二进制而非全局phpunit,支持通过composer test -- --filter=TestName传参,注意确保vendor/bin/phpunit存在且可执行。

composer.json 里怎么配 test 脚本
Composer 脚本本质是命令行指令的快捷别名,test 脚本不是内置功能,得手动定义。关键不是“能不能跑测试”,而是“用什么命令跑”——这取决于你实际用的测试框架。
常见组合:PHPUnit(PHP)、Pest(PHP)、或自定义 phpunit 可执行文件路径。别直接写 phpunit,除非确保它在 PATH 里全局可用;更稳妥的是用 vendor 里的二进制:
"scripts": {
"test": "vendor/bin/phpunit --colors=always"
}
- 如果项目用 Pest,改用
vendor/bin/pest - 想只跑某个目录?加参数:
"test": "vendor/bin/phpunit tests/Unit" - 需要生成代码覆盖率?补上
--coverage-html coverage,但注意这会显著拖慢执行速度
怎么让 test 脚本支持不同环境参数
硬编码参数不灵活,比如本地想看详细输出,CI 环境要静默+失败即停。Composer 脚本支持环境变量透传和参数占位符。
composer test -- --filter=TestName 这种写法,双横线后的内容会原样传给脚本命令;而 $argv 在脚本中不可用,得靠 $_SERVER['argv'] 或更推荐的方式:用环境变量控制分支逻辑。
- CI 环境常用
COMPOSER_NO_INTERACTION=1配合--no-ansi关闭颜色输出 - 想区分本地/CI 行为?在脚本里判断:
"test": "if [ \"$CI\" = \"true\" ]; then vendor/bin/phpunit --no-ansi; else vendor/bin/phpunit --colors=always; fi" - Windows 用户注意:上面的 shell 判断在 Windows CMD 下不生效,得用
scripts-windows单独配,或统一用 PHP 脚本封装
为什么 test 脚本执行时报 “Command not found”
最常见原因是 vendor/bin/phpunit 文件不存在,或权限不对。Composer 安装依赖后,bin 目录下的可执行文件是符号链接(Linux/macOS)或批处理包装器(Windows),但某些 CI 环境(如 Alpine Linux)默认不支持符号链接,或 vendor 没有被正确生成。
- 先确认
vendor/autoload.php存在,再检查vendor/bin/phpunit是否可执行:ls -l vendor/bin/phpunit - 如果它是空文件或损坏,运行
composer install --no-dev后又删了 dev 依赖,会导致phpunit消失——必须带--dev(默认开启)安装 - Git 忽略了
vendor/,CI 中靠composer install拉取,但没指定--with-all-dependencies,可能漏装 require-dev 下的间接依赖
能否在 test 前自动启动测试数据库或 Mock 服务
可以,但别塞进单个 test 脚本里。Composer 脚本适合串行轻量操作,复杂流程(如启 Docker、等端口就绪、清理状态)容易失控,失败时难以定位。
更可靠的做法是:用独立 shell 脚本或 Makefile 封装完整测试流程,Composer 脚本只做入口跳转。
- 例如写一个
./scripts/test.sh,里面启动docker-compose up -d db,等待端口开放,再调用vendor/bin/phpunit - 然后 Composer 脚本简化为:
"test": "bash ./scripts/test.sh" - 如果坚持纯 Composer 方案,可用
symfony/process写 PHP 封装器,但调试成本高,CI 日志也不直观
真正容易被忽略的是:测试前的环境清理(比如清 Redis、重置 SQLite 文件)和测试后的资源释放(关 Docker、删临时文件)。这些逻辑一旦写死在 Composer 脚本里,本地开发反复运行时容易残留状态,导致“上次测试影响下次结果”。











