应重点关注未执行的方法(如模型验证、钩子),并手动将业务代码目录加入phpunit.xml.dist的,注意suffix=".php"和路径前缀;排除需显式声明子目录;报告空白多因路径错误、权限不足或Xdebug未启用。

直接看 coverage-report/index.html 里的 HTML 报告,别先盯着百分比——真正要关注的是「哪些方法根本没被执行过」,尤其是模型验证逻辑、异常分支、beforeSave 或 afterFind 这类钩子。
phpunit.xml.dist 的 <include></include> 和 <exclude></exclude> 决定报告范围
Yii 2 默认只分析 framework/ 目录下的 PHP 文件,但你项目自己的业务代码(比如 common/models/、modules/api/controllers/)不会被覆盖,除非手动加进 <include></include>。常见错误是只改了 <directory></directory> 路径却漏掉 suffix=".php",导致文件不被识别。
-
<include></include>必须写全路径前缀,例如<directory suffix=".php">common/models</directory> -
<exclude></exclude>会跳过匹配目录,但不会递归排除子目录,想排除tests/下的辅助类,得单独加一行<directory suffix=".php">tests/helpers</directory> - 如果用了
yii2-app-advanced模板,console/和backend/的代码默认不在覆盖率范围内,需分别配置
--coverage-html 生成后打开报错或空白?检查三个地方
生成命令看似成功,但打开 coverage-report/index.html 是白页或控制台报 Failed to load resource,大概率是路径或权限问题。
- 确保执行命令时在项目根目录(即有
phpunit.xml.dist的位置),否则./vendor/bin/phpunit可能找不到配置 - 生成的
coverage-report/目录需对 Web 服务器可读;若用 PHP 内置服务器访问,不能直接双击打开 HTML,要用php -S localhost:8000 -t coverage-report - PHP 8.2 下如果提示
Class "SebastianBergmann\CodeCoverage\Driver\Xdebug2Driver" not found,说明 xdebug 未启用或版本不兼容,运行php -v确认 xdebug 是否加载,再查php --ri xdebug输出中是否含Enabled
语句覆盖率高 ≠ 测试质量高:警惕「假阳性」分支
Yii 中大量使用条件赋值、短路逻辑和数组键存在性判断(如 isset($this->attributes[$name])),这些语句即使被「执行」了,也不代表所有分支都被验证过。
-
if ($model->status === self::STATUS_ACTIVE || $user->isAdmin):覆盖率可能显示该行已覆盖,但只测了$user->isAdmin === true一种情况,||左边分支实际没走 -
return $this->getRelation('profile') ?: new Profile();:三元表达式里?:右侧构造新对象的代码,只有在关联为空时才执行,容易遗漏 - 模型规则中的
'on' => ['create']场景限制,若测试没显式传scenario = 'create',对应验证规则永远不会触发,但语句仍算“已执行”
真正难覆盖的是动态行为:事件监听器注册时机、behaviors() 返回的匿名函数、以及依赖容器自动解析的组件调用链。这些不会出现在静态分析里,得靠日志或断点确认是否真进了回调体。


















