阅读 SDebug README 有如下说明

The name of the extension is sdebug instead of xdebug, if you want to use Phpunit CodeCoverage, you have to manually modify xdebug to be sdebug.

为了避免 swoole 的检测 xdebug 警告, 扩展注册的名称是 sdebug, 如果想使用 Phpunit CodeCoverage , 需要手动把检测 xdebug 的判断修改成 sdebug。

因此需要对如下文件进行修改

vendor/sebastian/environment/src/Runtime.php

1
 211       return ($this->isPHP() || $this->isHHVM()) && (extension_loaded('xdebug')|| \extension_loaded('sdebug'));

vendor/phpunit/php-code-coverage/src/Driver/Selector.php

1
2
3
4
...
42            if (version_compare(phpversion('sdebug'), '3', '>=')) {
...
65            if (version_compare(phpversion('sdebug'), '3', '>=')) {

vendor/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php

1
2
3
4
5
6
7
8
...
48        if (!extension_loaded('sdebug')) {
...
52        if (version_compare(phpversion('sdebug'), '3', '>=')) {
...
79        $this->pathCoverageIsMixedCoverage = version_compare(phpversion('sdebug'), '2.9.6', '<');
...
126        return 'Xdebug ' . phpversion('sdebug');

vendor/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php

1
2
3
4
5
6
...
48        if (version_compare(phpversion('sdebug'), '3', '<')) {
...
52                    phpversion('sdebug')
...
117        return 'Xdebug ' . phpversion('sdebug');
  • 修改完上述文件代码后修改 phpunint.xml

  • 去除 coverage 标签中 processUncoveredFiles="true" 否则会抛出异常

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Fatal error: Cannot declare class App\Controller\AbstractController, because the name is already in use in /home/dickens7/worker/code/hyperf-skeleton/app/Controller/AbstractController.php on line 19

Call Stack:
    0.0005    1449288   1. {closure:/home/dickens7/worker/code/hyperf/src/testing/co-phpunit:8-68}() /home/dickens7/worker/code/hyperf/src/testing/co-phpunit:0
    0.0130    5341448   2. PHPUnit\TextUI\Command::main() /home/dickens7/worker/code/hyperf/src/testing/co-phpunit:65
    0.0130    5341560   3. PHPUnit\TextUI\Command->run() /home/dickens7/worker/code/hyperf-skeleton/vendor/phpunit/phpunit/src/TextUI/Command.php:96
    7.9843   84339040   4. PHPUnit\TextUI\TestRunner->run() /home/dickens7/worker/code/hyperf-skeleton/vendor/phpunit/phpunit/src/TextUI/Command.php:143
    8.0005   85614104   5. SebastianBergmann\CodeCoverage\Report\Html\Facade->process() /home/dickens7/worker/code/hyperf-skeleton/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:737
    8.0006   85617328   6. SebastianBergmann\CodeCoverage\CodeCoverage->getReport() /home/dickens7/worker/code/hyperf-skeleton/vendor/phpunit/php-code-coverage/src/Report/Html/Facade.php:54
    8.0168   85673752   7. SebastianBergmann\CodeCoverage\Node\Builder->build() /home/dickens7/worker/code/hyperf-skeleton/vendor/phpunit/php-code-coverage/src/CodeCoverage.php:139
    8.0168   85673752   8. SebastianBergmann\CodeCoverage\CodeCoverage->getData() /home/dickens7/worker/code/hyperf-skeleton/vendor/phpunit/php-code-coverage/src/Node/Builder.php:44
    8.0168   85673752   9. SebastianBergmann\CodeCoverage\CodeCoverage->processUncoveredFilesFromFilter() /home/dickens7/worker/code/hyperf-skeleton/vendor/phpunit/php-code-coverage/src/CodeCoverage.php:167
    8.0874   85675928  10. include_once('/home/dickens7/worker/code/hyperf-skeleton/app/Controller/AbstractController.php') /home/dickens7/worker/code/hyperf-skeleton/vendor/phpunit/php-code-coverage/src/CodeCoverage.php:538
  • 增加目录 <directory suffix=".php">./runtime/container/proxy</directory> 将代理类也加入测试覆盖范围
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<!--?xml version="1.0" encoding="UTF-8"?-->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupglobals="false" backupstaticattributes="false" bootstrap="./test/bootstrap.php" colors="true" converterrorstoexceptions="true" convertnoticestoexceptions="true" convertwarningstoexceptions="true" processisolation="false" stoponfailure="false" xsi:nonamespaceschemalocation="https://schema.phpunit.de/9.3/phpunit.xsd">
  <coverage>
    <include>
      <directory suffix=".php">./app</directory>
      <directory suffix=".php">./runtime/container/proxy</directory>
    </include>
  </coverage>
  <testsuites>
    <testsuite name="Tests">
      <directory suffix="Test.php">./test</directory>
    </testsuite>
  </testsuites>
</phpunit>

运行测试

co-phpunit -c phpunit.xml --colors=always --coverage-html ./runtime/codeCoverage

image

执行成功后 会在 ./runtime/codeCoverage 中生产对应测试报告

image

测试报告生产出来了,但是覆盖率始终未 0

cs-fix 会添加 @coversNothing 去除 test/Cases/ExampleTest.php中的 @coversNothing 再次执行 co-phpunit -c phpunit.xml --colors=always --coverage-html ./runtime/codeCoverage 就能正确的生产测试覆盖率报告了

image

与 Hyperf 2.0 差异

hyperf 2.1 对 phpunit 的依赖从 ^7.0.0 提升到 ^9.4 阅读 PHPunit 的 ChangeLog-8.5 可知 phpunit 支持了 xdebug 3

vendor/phpunit/php-code-coverage/src/Driver/Xdebug.php 被拆分分为了 vendor/phpunit/php-code-coverage/src/Driver/Xdebug3Driver.php vendor/phpunit/php-code-coverage/src/Driver/Xdebug2Driver.php

因此hyperf 2.0 要支持测试覆盖率只需将 Xdebug3Driver、Xdebug2Driver 的修改调整为修改

vendor/phpunit/php-code-coverage/src/Driver/Xdebug.php

1
32        if (! \extension_loaded('xdebug') && ! \extension_loaded('sdebug')) {