PHP 单元测试覆盖率

由于绩效中写到了代码的单元测试覆盖率,于是就准备在每次需求上线前导出下覆盖率报告,就有了下面的配置。

首先,覆盖率的统计需要用到扩展 xdebug ,所以先安装下:

pecl install xdebug

可能需要手动添加 zend_extension=xdebug.so

这里给出一份我本地的测试。目录结构是这样的:

├── app
│   └── Demo.php
├── composer.json
├── composer.lock
├── phpunit.xml
├── test-result
│   └── report
│       ├── Demo.php.html
│       ├── dashboard.html
│       └── index.html
└── tests
    └── DemoTest.php

phpunitx.xml的配置内容如下:

<phpunit
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
   bootstrap="./vendor/autoload.php"
   colors="true"
   convertErrorsToExceptions="true"
   convertNoticesToExceptions="true"
   convertWarningsToExceptions="true"
   processIsolation="false"
   stopOnError="true"
   stopOnFailure="true"
   stopOnIncomplete="false"
   stopOnSkipped="false"
   stopOnRisky="false"
   verbose="false">
   <testsuites>
     <testsuite name="TestSuite">
       <directory>./tests/</directory>
     </testsuite>
   </testsuites>
   <filter>
     <whitelist addUncoveredFilesFromWhitelist="true" processUncoveredFilesFromWhitelist="true">
       <file>./app/Demo.php</file>
     </whitelist>
   </filter>
   <logging>
     <log type="coverage-html" target="./test-result/report" lowUpperBound="35"
          highLowerBound="70"/>
   </logging>
</phpunit>

composer.json 文件内容如下:

{
    "require": {
        "phpunit/phpunit": "^7.5"
    },
    "autoload": {
        "psr-4": {
            "App\\": "./app",
            "Test\\": "./tests"
        }
    }
}

App/Demo.php 文件内容如下:

<?php
namespace App;
class Demo
{

    public function demo1($status)
    {
        if ($status == 1) {
            return '未支付';
        } else if ($status == 2) {
            return '等待支付';
        } else {
            return '已支付';
        }
    }
    public function demo2()
    {
        return 123;
    }
}

DemoTest.php 文件内容如下:

<?php

namespace Test;

use App\Demo;
use PHPUnit\Framework\TestCase;

class DemoTest extends TestCase
{

    /**
     * @covers \App\Demo::demo1
     */
    public function testDemo1()
    {
        $result = (new Demo)->demo1(1);
        $this->assertEquals('未支付', $result);

        $result = (new Demo)->demo1(2);
        $this->assertEquals('等待支付', $result);

        $result = (new Demo)->demo1(3);
        $this->assertEquals('已支付', $result);
    }

}

上面这些是一个简单的单元测试,这里注意下 phpunit.xml 的配置,其中的 filter 中的标签是开启单元测试的覆盖率分析,其中设置了哪些文件需要分析覆盖率。 logging 标签里面配置了单元测试覆盖率报告,报告格式有很多,我这里选择了 html 格式,便于直接查看。接下来,我们可以跑下:

~ learn-phpunit ./vendor/bin/phpunit
PHPUnit 7.5.2 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 51 ms, Memory: 4.00MB

OK (1 test, 3 assertions)

Generating code coverage report in HTML format ... done

测试成功,我们打开 test-result/report/index.html 文件,可以看到:

file

点击 Demo.php 可以看到

file

到这里,单元测试覆盖率的导出基本上就可以使用了。但是,还有一个问题,在团队开发当中,很多时候我们只是编写了一个文件中的部分代码,那么如果我们只想对这部分代码进行覆盖率测试,该怎么办呢?

这里我们可以利用 @codeCoverageIgnoreStart@codeCoverageIgnoreEnd 两个标签。例如上,上面的 Demo.php 文件,我们只想对 demo1 方法的覆盖率进行统计,于是我们可以这么做:

<?php

namespace App;

class Demo
{

    public function demo1($status)
    {
        if ($status == 1) {
            return '未支付';
        } else if ($status == 2) {
            return '等待支付';
        } else {
            return '已支付';
        }
    }

    // @codeCoverageIgnoreStart
    public function demo2()
    {
        return 123;
    }

    // @codeCoverageIgnoreEnd

}

用这两个标签将不需要分析的代码包裹起来就可以啦。我们来看下覆盖率分析报表:

file

OK,就到这里了。

======

PHP单元测试视频教程

本作品采用《CC 协议》,转载必须注明作者和本文链接
开源教育系统https://meedu.vip
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 1

拓展一下,可使用 Coveralls 等服务对测试覆盖率进行收集,例如我的项目:https://github.com/wi1dcard/alipay-sdk-php

Coverage Status

集成 CI 后,可在每次执行单元测试时将报告提交至 Coveralls。我使用 Travis CI,配置如下:

# ...
after_script:
  - |
    if [[ $MORE != "" ]]; then
      wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.1.0/php-coveralls.phar;
      php php-coveralls.phar -v;
    fi
# ...

after_script 内,下载 Coveralls 的 PHAR,随后执行该 PHAR 包,即可采集位于 build/logs/clover.xml 的测试覆盖率报告,并上传至 Coveralls 了。

欲生成该 XML 格式的测试报告文件,可使用 phpunit --coverage-clover build/logs/clover.xml

或在 phpunit.xml 内配置如下内容:

<phpunit ...>
    <logging>
        ...
        <log type="coverage-clover" target="build/logs/clover.xml"/>
        ...
    </logging>
</phpunit>
5年前 评论

拓展一下,可使用 Coveralls 等服务对测试覆盖率进行收集,例如我的项目:https://github.com/wi1dcard/alipay-sdk-php

Coverage Status

集成 CI 后,可在每次执行单元测试时将报告提交至 Coveralls。我使用 Travis CI,配置如下:

# ...
after_script:
  - |
    if [[ $MORE != "" ]]; then
      wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.1.0/php-coveralls.phar;
      php php-coveralls.phar -v;
    fi
# ...

after_script 内,下载 Coveralls 的 PHAR,随后执行该 PHAR 包,即可采集位于 build/logs/clover.xml 的测试覆盖率报告,并上传至 Coveralls 了。

欲生成该 XML 格式的测试报告文件,可使用 phpunit --coverage-clover build/logs/clover.xml

或在 phpunit.xml 内配置如下内容:

<phpunit ...>
    <logging>
        ...
        <log type="coverage-clover" target="build/logs/clover.xml"/>
        ...
    </logging>
</phpunit>
5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!