小滕的博客

小滕的技术点滴

php单元测试的覆盖率

3 weeks ago · 1 MIN READ
#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 文件,可以看到:

WX20190124-134722@2x.png

点击 Demo.php 可以看到

WX20190124-134846@2x.png

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

这里我们可以利用 @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

}

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

WX20190124-135312@2x.png

OK,就到这里了。

======

单元测试视频教程

···

xiao teng



Proudly powered by Canvas · Sign In