最近在玩PHP的单元测试,以及代码覆盖率这块,也遇到一些问题,所以摘出来记录一下,也算是简单入门了。

1.安装PHPUnit

可参考《PHPUnit官方安装教程》,比较简单,基本只要把文件下载到本地即可。
同时可看看PHPUnit的官方教程,了解一些必要的基础知识。

2.单元测试简单例子

用 PHPUnit 编写测试的基本惯例与步骤:

  • 针对类 Class 的测试写在类 ClassTest中。
  • ClassTest(通常)继承自PHPUnit\Framework\TestCase。
  • 测试都是命名为 test* 的公用方法。
    也可以在方法的文档注释块(docblock)中使用 @test 标注将其标记为测试方法。
  • 在测试方法内,类似于 assertEquals()(参见 PHPUnit官方文档)这样的断言方法用来对实际值与预期值的匹配做出断言。
  • @depends 标注来表达测试方法之间的依赖关系
<?php
use PHPUnit\Framework\TestCase;

class StackTest extends TestCase
{
    public function testEmpty()
    {
        $stack = [];
        $this->assertEmpty($stack);

        return $stack;
    }

    /**
     * @depends testEmpty
     */
    public function testPush(array $stack)
    {
        array_push($stack, 'foo');
        $this->assertEquals('foo', $stack[count($stack)-1]);
        $this->assertNotEmpty($stack);

        return $stack;
    }

    /**
     * @depends testPush
     */
    public function testPop(array $stack)
    {
        $this->assertEquals('foo', array_pop($stack));
        $this->assertEmpty($stack);
    }
}
?>

运行测试&结果:

phpunit --verbose StackTest.php 

PHPUnit 7.1.5 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.1.14 with Xdebug 2.5.5

...                                                                 3 / 3 (100%)

Time: 149 ms, Memory: 10.00MB

OK (3 tests, 5 assertions)

3.代码覆盖率的报告

1).从一个github项目上开始玩

参考项目:

git clone https://github.com/sebastianbergmann/money.git

执行测试:

phpunit --configuration build/phpunit.xml
//或者如下执行方式也行
php build/tools/phpunit.phar --configuration build/phpunit.xml

报错如下:

PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.0.27
Configuration: /alidata1/home/yisonli/test/money/build/phpunit.xml
Error:         No code coverage driver is available

...........S................................                      44 / 44 (100%)

Time: 198 ms, Memory: 8.00MB

There was 1 skipped test:

1) SebastianBergmann\Money\IntlFormatterTest
Extension intl is required.

OK, but incomplete, skipped, or risky tests!
Tests: 44, Assertions: 69, Skipped: 1.

2).安装xdebug

具体安装可参考《xdebug源码安装》,之所以采用源码方式安装,是因为brew已经不提供自动安装了,只好下源码自行编译。

提示:PHP扩展目录(以自己安装PHP的path为准)

/usr/local/php7.0/lib/php/extensions/no-debug-non-zts-20151012
/* MAC默认目录可能是:/usr/lib/php/extensions/no-debug-non-zts-20160303 */

3).重新执行测试即可生成报告

phpunit --configuration build/phpunit.xml 

PHPUnit 7.1.5 by Sebastian Bergmann and contributors.

Runtime:       PHP 7.1.14 with Xdebug 2.5.5
Configuration: /Users/yison/GitProject/money/build/phpunit.xml

...........S................................                      44 / 44 (100%)

Time: 775 ms, Memory: 18.00MB

There was 1 skipped test:

1) SebastianBergmann\Money\IntlFormatterTest
Extension intl is required.

OK, but incomplete, skipped, or risky tests!
Tests: 44, Assertions: 69, Skipped: 1.

Generating code coverage report in Clover XML format ... done

Generating Crap4J report XML file ... done

Generating code coverage report in HTML format ... done

Generating code coverage report in PHPUnit XML format ... done

此时在build文件夹下就有你想要看的覆盖率报告了。

4.PHPUnit指令和xml配置,了解一下

Whitelisting Files for Code Coverage

<filter> 元素及其子元素用于配置代码覆盖率报告所使用的白名单。

<filter>
  <whitelist processUncoveredFilesFromWhitelist="true">
    <directory suffix=".php">/path/to/files</directory>
    <file>/path/to/file</file>
    <exclude>
      <directory suffix=".php">/path/to/files</directory>
      <file>/path/to/file</file>
    </exclude>
  </whitelist>
</filter>

Logging (日志记录)

<logging> 元素及其 <log> 子元素用于配置测试执行期间的日志记录。

<logging>
  <log type="coverage-html" target="/tmp/report" lowUpperBound="35"
       highLowerBound="70"/>
  <log type="coverage-clover" target="/tmp/coverage.xml"/>
  <log type="coverage-php" target="/tmp/coverage.serialized"/>
  <log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/>
  <log type="junit" target="/tmp/logfile.xml" logIncompleteSkipped="false"/>
  <log type="testdox-html" target="/tmp/testdox.html"/>
  <log type="testdox-text" target="/tmp/testdox.txt"/>
</logging>

以上 XML 配置对应于以如下选项调用 TextUI 测试执行器:

--coverage-html /tmp/report

--coverage-clover /tmp/coverage.xml

--coverage-php /tmp/coverage.serialized

--coverage-text

> /tmp/logfile.txt

--log-junit /tmp/logfile.xml

--testdox-html /tmp/testdox.html

--testdox-text /tmp/testdox.txt

lowUpperBound、highLowerBound、logIncompleteSkipped 及 showUncoveredFiles 属性没有等价的 TextUI 测试执行器选项。

lowUpperBound:视为“低”覆盖率的最大覆盖率百分比。

highLowerBound:视为“高”覆盖率的最小覆盖率百分比。

showUncoveredFiles:在 --coverage-text 输出中显示所有符合白名单的文件,不仅限于有覆盖率信息的那些。

showOnlySummary:在 --coverage-text 输出中只显示摘要

5.最后展示一下报告的html效果吧

总览

单个测试结果

异常标注