根本原因是CI默认执行composer install --no-dev,只加载autoload段而忽略autoload-dev,导致测试基类无法被src中代码引用;需检查autoload命名空间一致性、启用dev autoload、使用composer test而非直接调用phpunit,并在CI中验证dump-autoload。

CI 里跑 composer test 报 “Class not found”,八成不是 PHPUnit 配置错了,而是 composer.json 的 autoload 没对上源码命名空间,或者 CI 没加载 dev autoload。
为什么本地 test 能过,CI 却找不到类
根本原因:CI 默认执行 composer install --no-dev,只加载 autoload 段,完全忽略 autoload-dev。如果你的测试基类(比如 tests/Support/TestCase.php)被写进了 autoload-dev,但又在 src/ 里 use 它——CI 就会炸。
- 检查
composer.json的"autoload": { "psr-4": { "MyPackage\": "src/" } }是否和你实际类的命名空间(如MyPackageCalculator)完全一致 - 运行
composer show my/package,看输出中autoload行是否匹配 - CI 中加验证命令:
composer dump-autoload --no-dev && php -r "echo class_exists('MyPackage\Calculator') ? 'ok' : 'fail';"
phpunit.xml.dist 必须存在的三个配置项
漏掉任意一个,覆盖率统计、IDE 跳转、甚至类自动加载都可能失效。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
-
bootstrap="vendor/autoload.php":确保测试能加载你的类,别用空字符串或相对路径 -
<directory>tests</directory>:明确告诉 PHPUnit 测试入口在哪,不是test或Tests -
<source><directory>src</directory></source>:没有它,--coverage-html会漏文件,class_exists()在某些上下文也可能返回 false
CI 脚本里该用 composer test,而不是直接调 phpunit
直接跑 ./vendor/bin/phpunit 会绕过 phpunit.xml.dist 里的 <source>,导致“本地能跑、CI 找不到类”;而 composer test 是标准化出口,所有环境行为一致。
- 确保
composer.json的scripts里定义了"test": "phpunit"(不是硬编码路径) - CI 中统一用
composer test -- --fail-on-warning --no-coverage,避免生成无用报告、把 deprecation 当警告放过 - 别在脚本里写
phpunit --configuration phpunit.xml——.dist后缀是给 Composer 和 CI 用的默认约定,PHPUnit 本身优先读.xml,容易误加载错配置
GitHub Actions 里最关键的三件事
缓存、PHP 版本矩阵、依赖安装方式,这三项错一个,CI 就不可靠。
- 缓存目标必须是
~/.composer/cache,不是vendor/——后者在不同 PHP minor 版本间不兼容,会引发随机 autoload 失败 - PHP 版本用矩阵:
php-version: [8.1, 8.2, 8.3],别写死8.2,否则主版本更新后整个 CI 突然全挂 - CI 第一步必须是
composer validate --no-check-publish,提前拦截composer.json格式错误或字段非法,比等测试失败再排查快得多
最常被跳过的其实是 composer dump-autoload --no-dev 这步验证——它不报错,但一旦失败,后续所有 class_exists() 判断都不可信。CI 日志里没显式失败,不等于它成功了。

















