PHP单元测试框架 - PHPUnit介绍

李星辰
2023-12-01

介绍:

PHPUnit是一个轻量级的PHP测试框架。它是在PHP5下面对JUnit3系列版本的完整移植,是xUnit测试框架家族的一员(它们都基于模式先锋Kent Beck的设计)。


安装:

依赖:php环境,需要提前安装,详细这里就不介绍了

Linux安装:

$ wget https://phar.phpunit.de/phpunit.phar

$ chmod +x phpunit.phar

$ sudo mv phpunit.phar /usr/local/bin/phpunit

$ phpunit –version

Windows安装:

安装php和pear

运行:

pear config-set auto_discover 1

pear install pear.phpunit.de/PHPUnit

运行phpunit –version 验证安装结果


Phpunit编写惯例:

1、 类Class的测试写在ClassTest中;

2、 ClassTest继承自PHPUnit_Framework_TestCase;

3、 测试都是命名为test*的公用方法(也可以在方法的docblock中使用@test标注);

4、 在测试方法内使用断言对实际值与预期值做匹配。

例:

//类继承自PHPUnit_Framework_TestCase
class ClassTest extends PHPUnit_Framework_TestCase
{
    //测试方法:以test开头
    public function testPushAndPop()    
    {
        $stack array();
        //断言:对预期值与实际值左匹配
        $this->assertEquals(0count($stack));  
    }
}

运行结果:

Time: 0 seconds, Memory: 2.00Mb

OK (1 test, 1 assertion)


开始测试:

目录结构:

|--src 被测程序目录

|--test 测试脚本存放目录  (测试脚本与被测脚本分开)

被测类:./src/ExampleClass.php

<?php
class ExampleClass
{
    function add($a,$b){
        return $a $b;
    }
}
?>

测试脚本:./test/ExampleClassTest.php

<?php
//包含被测类
require_once('./test/ExampleClass.php');
class ClassTest extends PHPUnit_Framework_TestCase
{
function testAdd(){
     //实例化被测类
     $obj new ExampleClass();
     //引用并断言被测方法
     $this->assertEquals(3,$obj->add(1,2)); //失败的断言
     $this->assertEquals(3,$obj->add(1,1)); //正确的断言
}

}

执行测试:

运行如下命令,指定要执行的测试脚本:

$ phpunit ./test/ExampleClassTest.php

或:

执行被测脚本所在的目录,phpunit自动寻找*test.php结尾的文件并执行测试

$ phpunit ./test/

或:

使用—bootstrap参数,在运行测试代码前先加载./src/ExampleClass.php

Phpunit --bootstrap ./src/ExampleClass.php ./test/ExampleClassTest.php

测试结果:

PHPUnit 3.7.21 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 2.00Mb

There was 1 failure:

1) ClassTest::testAdd

Failed asserting that 2 matches expected 3.

C:\xampp\htdocs\test\ExampleClassTest.php:11

FAILURES!

Tests: 1, Assertions: 2, Failures: 1.


依赖:

依赖允许生产者返回一个测试基境的实例,并将此实例传递给依赖于它的消费者们。

在注释中用@depends标注来声明依赖关系。

例:

<?php
//包含被测类
require_once('./test/ExampleClass.php');
class ExampleClassTest extends PHPUnit_Framework_TestCase
{
    public function testAdd(){
        //实例化被测类
        $obj new ExampleClass();
        $n $obj->add(1,2);
        $this->assertEquals(3,$n);
        return $n;
    }

    /**
     * @depends testAdd
     */
    public function testSub($n){
        $s $n 1;
        $this->assertEquals(2,$s);
    }
}

注释:在第一个测试testAdd()中,计算了1+2的和,赋值给$n并返回;第二个测试testSub()依赖于testAdd(),并将所依赖的测试结果$n作为参数传入并计算$n-1。


利用测试之间的历来关系,当所依赖的测试失败时phpunit会跳过此测试:

例:

<?php
//包含被测类
require_once('./test/ExampleClass.php');
class ExampleClassTest extends PHPUnit_Framework_TestCase
{
    public function testAdd(){
        //实例化被测类
        $obj new ExampleClass();
        $n $obj->add(1,2);
        $this->assertEquals(2,$n);
        return $n;
    }
    /**
     * @depends testAdd
     */
    public function testSub($n){
        $s $n 1;
        $this->assertEquals(2,$s);
    }
    
    public function  testResult(){
        echo ("测试完成");
    }
}

运行结果:

Failed asserting that 3 matches expected 2.

Expected :2

Actual   :3

 <Click to see difference>

 C:\xampp\htdocs\test\ExampleClassTest.php:10

This test depends on "ExampleClassTest::testAdd" to pass.测试完成

Time: 7 seconds, Memory: 3.00Mb

FAILURES!

Tests: 2, Assertions: 1, Failures: 1, Skipped: 1.

注释:测试testAdd()断言失败,由于测试testSub()依赖testAdd(),而testAdd()失败,所以testSub()没有执行;testResult()返回“测试完成”。


数据供给器:

测试方法可以接受任意参数,这些参数可以由数据供给器方法提供。

用@dataProvider标注来指定使用哪个数据供给器方法。

数据供给器方法必须声明为public,其返回值可以是一个数组,其每个元素也是数组;也可以是一个实现了Iterator接口的对象,在对它进行迭代时每步产生一个数组。

每个数组都是测试数据的一部分,将以它的内容作为参数来调用测试方法。

例:

<?php
//包含被测类
require_once('./test/ExampleClass.php');
class ExampleClassTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider additionProvider
     */
    public function testAdd($a,$b,$c){
        //实例化被测类
        $obj new ExampleClass();
        $n $obj->add($a,$b);
        $this->assertEquals($c,$n);
    }
    public function additionProvider(){
        return array(
            array(0,0,0),
            array(0,1,1),
            array(1,1,3)
        );
    }
}

运行结果:

Failed asserting that 2 matches expected 3.

Expected :3

Actual   :2

  <Click to see difference>

  C:\xampp\htdocs\test\ExampleClassTest.php:13

 

Time: 7 seconds, Memory: 3.00Mb

FAILURES!

Tests: 3, Assertions: 3, Failures: 1.


扩展:

基境:

对开始执行某个测试时应用程序和数据库所处初始状态的描述。

setup()  在运行测试方法之前调用,用于创建测试所用对象。

teardown() - 在测试方法运行后调用,用于清理测试所用对象。

setUpBeforeClass()  在测试用例类的第一个测试运行之前调用。

tearDownAfterClass()  在测试用例类的最后一个测试运行之后调用。


组织测试:

目录方式:把所有测试用例源文件放在一个测试目录中。通过对测试目录进行递归遍历,PHPUnit 能自动发现并运行测试

Xml配置方式:编辑phpunit.xml或phpunit.xml.dist


数据库测试:

安装DbUnit扩展

使用PHPUnit_Extensions_Database_TestCase方法

初始化数据库中测试数据

断言数据集,断言内容可以包括(表中的数据行数、表状态、查询结果等)


常用断言:

AssertTrue/AssertFalse    断言是否为真值还是假
AssertEquals    判断输出是否和预期的相等
AssertGreaterThan    断言结果是否大于某个值,同样的也有LessThan(小于),GreaterThanOrEqual(大于等于),LessThanOrEqual(小于等于).
AssertContains    判断输入是否包含指定的值
AssertType    判断是否属于指定类型
AssertNull    判断是否为空值
AssertFileExists    判断文件是否存在
AssertRegExp    根据正则表达式判断


PHPUnit常用命令行选项:

--coverage-clover  为运行的测试生成带有代码覆盖率信息的 XML 格式的日志文件

--log-junit为运行的测试生成 JUnit XML 格式的日志文件

--verbose输出更详尽的信息,例如不完整或者跳过的测试的名称

--repeat将测试重复运行指定次数

--bootstrap在测试前先运行一个 "bootstrap" PHP 文件

--configuration, -c 从 XML 文件中读取配置信息

参考:https://phpunit.de/manual/current/zh_cn/phpunit-book.html



 类似资料: