PHPUnit的使用

Composer 安装PHPUnit

composer global require "phpunit/phpunit=5.5.*"  //安装特定版本
composer global require "phpunit/phpunit"  //安装默认版本

会将PHPUnit以全局的形式安装到电脑当中去 
确保.bash_profile文件包含命令路径 
phpunit —help可以查看命令

对于每个测试的运行,PHPUnit 命令行工具输出一个字符来指示进展:

.

当测试成功时输出。

F

当测试方法运行过程中一个断言失败时输出。

E

当测试方法运行过程中产生一个错误时输出。

R

当测试被标记为有风险时输出(参见第 6 章)。

S

当测试被跳过时输出(参见第 7 章)。

I

当测试被标记为不完整或未实现时输出(参见第 7 章)。

PHPUnit 区分 败(failure)错误(error)。失败指的是被违背了的 PHPUnit 断言,例如一个失败的 assertEquals() 调用。错误指的是意料之外的异常(exception)或 PHP 错误。这种差异已被证明在某些时候是非常有用的,因为错误往往比失败更容易修复。如果得到了一个非常长的问题列表,那么最好先对付错误,当错误全部修复了之后再试一次瞧瞧还有没有失败。

目录架构

当你想把一些东西写到 print 语句或者调试表达式中时,别这么做,将其写成一个测试来代替。                           --Martin Fowler

例 2.1展示了如何用 PHPUnit 编写测试来对 PHP 数组操作进行测试。本例介绍了用 PHPUnit 编写测试的基本惯例与步骤:

  1. 针对类 Class 的测试写在类 ClassTest中。

  2. ClassTest(通常)继承自 PHPUnit\Framework\TestCase

  3. 测试都是命名为 test* 的公用方法。

    也可以在方法的文档注释块(docblock)中使用 @test 标注将其标记为测试方法。

  4. 在测试方法内,类似于 assertEquals()(参见 附录 A)这样的断言方法用来对实际值与预期值的匹配做出断言。

Stack.php 内容如下:

<?php
/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2018-07-20
 * Time: 下午 4:01
 */
use PHPUnit\Framework\TestCase;

class StackTest extends TestCase
{
    public function testPushAndPop(){
        //判断 0 是否等于 count $stack
        $stack = [];
        $this->assertEquals(0,count($stack));

        array_push($stack,'foo');
        //判断 foo 是否等于$stack[count($stack) - 1]
        $this->assertEquals('foo',$stack[count($stack) - 1]);
        //判断 1 是否等于 count $stack
        $this->assertEquals(1,count($stack));

        //判断 foo 是否等于 array_pop($stack) 的返回值
        $this->assertEquals('foo',array_pop($stack));
        //判断 0 是否等于 count $stack
        $this->assertEquals(0,count($stack));
    }

    public function testEmpty(){
        $stack = [];
        //判断 $stack 为空 是否真
        $this->assertEmpty($stack);
        return $stack;
    }

    /**
     * @depends testEmpty
    */
    public function testPush(array $stack){
        array_push($stack,'foo');
        //判断 foo 是否等于 $stack[count($stack)-1]
        $this->assertEquals('foo',$stack[count($stack)-1]);
        //判断 $stack 不为空 是否为真
        $this->assertNotEmpty($stack);

        return $stack;
    }

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

运行 Stack.php :

测试的依赖关系

 

单元测试主要是作为一种良好实践来编写的,它能帮助开发人员识别并修复 bug、重构代码,还可以看作被测软件单元的文档。要实现这些好处,理想的单元测试应当覆盖程序中所有可能的路径。一个单元测试通常覆盖一个函数或方法中的一个特定路径。但是,测试方法并不一定非要是一个封装良好的独立实体。测试方法之间经常有隐含的依赖关系暗藏在测试的实现方案中。

 
  --Adrian Kuhn et. al.

PHPUnit支持对测试方法之间的显式依赖关系进行声明。这种依赖关系并不是定义在测试方法的执行顺序中,而是允许生产者(producer)返回一个测试基境(fixture)的实例,并将此实例传递给依赖于它的消费者(consumer)们。

  • 生产者(producer),是能生成被测单元并将其作为返回值的测试方法。

  • 消费者(consumer),是依赖于一个或多个生产者及其返回值的测试方法。

例 2.2展示了如何用 @depends 标注来表达测试方法之间的依赖关系。

例 2.2: 用 @depends 标注来表达依赖关系

DependencyFailure.php 内容如下:

<?php
/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2018-07-20
 * Time: 下午 4:01
 */
use PHPUnit\Framework\TestCase;

class DependencyFailureTest extends TestCase
{
    public function testOne(){
        //assertTrue  判断 第一个参数是否为true ,如果为false ,返回 F
        $this->assertTrue(false);
    }

    /**
    * @depends testOne
     */
    public function testTwo(){
        // testTwo 依赖了 testOne
        //因为testOne 返回 F 测试失败,所以 testTwo将不再执行
    }

    public function testThree(){
        //testThree 没有依赖 testOne , 可以继续执行
        $this->assertTrue(true);
    }

    public function testEmpty(){
        $stack = [];
        //判断 $stack == empty 是否为真
        $this->assertEmpty($stack);

        return $stack;
    }

    /**
    * @depends testEmpty
     */
    public function testPush(array $stack){ //获取 testEmpty的返回值,并作为参数传入
        array_push($stack,'foo');
        // 判断 foo 是否等于 $stack[count($stack)-1]
        $this->assertEquals('foo',$stack[count($stack)-1]);
        // 判断 $stack != empty 是否为真
        $this->assertNotEmpty($stack);

        return $stack;
    }

    /**
    * @depends testPush
     */
    public function testPop(array $stack){ //获取 testPush的返回值,并作为参数传入
        //判断 foo  是否等于 array_pop($stack)的返回值
        $this->assertEquals('foo',array_pop($stack));
        //判断 $stack == empty 是否为真
        $this->assertEmpty($stack);
    }
}

运行   DependencyFailure.php :

在上例中,第一个测试, testEmpty(),创建了一个新数组,并断言其为空。随后,此测试将此基境作为结果返回。第二个测试,testPush(),依赖于 testEmpty() ,并将所依赖的测试之结果作为参数传入。最后,testPop() 依赖于 testPush()

注意

默认情况下,生产者所产生的返回值将“原样”传递给相应的消费者。这意味着,如果生产者返回的是一个对象,那么传递给消费者的将是一个指向此对象的引用。如果需要传递对象的副本而非引用,则应当用 @depends clone 替代 @depends

为了快速定位缺陷,我们希望把注意力集中于相关的失败测试上。这就是为什么当某个测试所依赖的测试失败时,PHPUnit 会跳过这个测试。通过利用测试之间的依赖关系,缺陷定位得到了改进,如例 2.3中所示。

测试可以使用多个 @depends 标注。PHPUnit 不会更改测试的运行顺序,因此你需要自行保证某个测试所依赖的所有测试均出现于这个测试之前。

拥有多个 @depends 标注的测试,其第一个参数是第一个生产者提供的基境,第二个参数是第二个生产者提供的基境,以此类推。参见例 2.4

例 2.4: 有多重依赖的测试

MultipleDependencies.php 的内容如下:
<?php
/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2018-07-20
 * Time: 下午 4:01
 */
use PHPUnit\Framework\TestCase;

class MultipleDependenciesTest extends TestCase
{
    public function testProducerFirst(){
        $this->assertTrue(true);
        return 'first';
    }

    public function testProducerSecond(){
        $this->assertTrue(true);
        return 'second';
    }

    /**
      * @depends testProducerFirst
      * @depends testProducerSecond
    */
    public function testConsumer(){
        $this->assertEquals(
            ['first','second'],
            //判断上面的数组 和 func_get_args 获取 depends 依赖返回的值 是否一致
            func_get_args()
        );
    }
}

运行 MultipleDependencies :

数据供给器

测试方法可以接受任意参数。这些参数由数据供给器方法(在 例 2.5中,是 additionProvider() 方法)提供。用 @dataProvider 标注来指定使用哪个数据供给器方法。

数据供给器方法必须声明为 public,其返回值要么是一个数组,其每个元素也是数组;要么是一个实现了 Iterator 接口的对象,在对它进行迭代时每步产生一个数组。每个数组都是测试数据集的一部分,将以它的内容作为参数来调用测试方法。

例 2.5: 使用返回数组的数组的数据供给器

Data.php 内容如下:

<?php
/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2018-07-20
 * Time: 下午 4:01
 */
use PHPUnit\Framework\TestCase;

class DataTest extends TestCase
{
    /**
      * @dataProvider additionProvider
      * @dataProvider additionProvider2
    */
    public function testAdd($a,$b,$expected){
        $this->assertEquals($expected,$a+$b);
    }

    public function additionProvider(){
        return [
            // $a = 0 $b = 0 $expected = 0
            [0,0,0],
            // $a = 0 $b = 1 $expected = 1
            [0,1,1],
            // $a = 1 $b = 0 $expected = 1
            [1,0,1],
            // $a = 1 $b = 1 $expected = 3
            [1,1,3],
        ];
    }

    public function additionProvider2(){
        return [
            // $a = 0 $b = 0 $expected = 0
            'adding zeros'=>[0,0,0],
            // $a = 0 $b = 1 $expected = 1
            'zero plus one'=>[0,1,1],
            // $a = 1 $b = 0 $expected = 1
            'one plus zero'=>[1,0,1],
            // $a = 1 $b = 1 $expected = 3
            'one plus one'=>[1,1,3],
        ];
    }
}

运行 Data.php:

断言
布尔类型
assertTrue 断言为真
assertFalse 断言为假

NULL类型
assertNull 断言为NULL
assertNotNull 断言非NULL

数字类型
assertEquals 断言等于
assertNotEquals 断言不等于
assertGreaterThan 断言大于
assertGreaterThanOrEqual 断言大于等于
assertLessThan 断言小于
assertLessThanOrEqual 断言小于等于

字符类型
assertEquals 断言等于
assertNotEquals 断言不等于
assertContains 断言包含
assertNotContains 断言不包含
assertContainsOnly 断言只包含
assertNotContainsOnly 断言不只包含

数组类型
assertEquals 断言等于
assertNotEquals 断言不等于
assertArrayHasKey 断言有键
assertArrayNotHasKey 断言没有键
assertContains 断言包含
assertNotContains 断言不包含
assertContainsOnly 断言只包含
assertNotContainsOnly 断言不只包含

对象类型
assertAttributeContains 断言属性包含
assertAttributeContainsOnly 断言属性只包含
assertAttributeEquals 断言属性等于
assertAttributeGreaterThan 断言属性大于
assertAttributeGreaterThanOrEqual 断言属性大于等于
assertAttributeLessThan 断言属性小于
assertAttributeLessThanOrEqual 断言属性小于等于
assertAttributeNotContains 断言不包含
assertAttributeNotContainsOnly 断言属性不只包含
assertAttributeNotEquals 断言属性不等于
assertAttributeNotSame 断言属性不相同
assertAttributeSame 断言属性相同
assertSame 断言类型和值都相同
assertNotSame 断言类型或值不相同
assertObjectHasAttribute 断言对象有某属性
assertObjectNotHasAttribute 断言对象没有某属性

class类型
class类型包含对象类型的所有断言,还有
assertClassHasAttribute 断言类有某属性
assertClassHasStaticAttribute 断言类有某静态属性
assertClassNotHasAttribute 断言类没有某属性
assertClassNotHasStaticAttribute 断言类没有某静态属性

文件相关
assertFileEquals 断言文件内容等于
assertFileExists 断言文件存在
assertFileNotEquals 断言文件内容不等于
assertFileNotExists 断言文件不存在

XML相关
assertXmlFileEqualsXmlFile 断言XML文件内容相等
assertXmlFileNotEqualsXmlFile 断言XML文件内容不相等
assertXmlStringEqualsXmlFile 断言XML字符串等于XML文件内容
assertXmlStringEqualsXmlString 断言XML字符串相等
assertXmlStringNotEqualsXmlFile 断言XML字符串不等于XML文件内容
assertXmlStringNotEqualsXmlString 断言XML字符串不相等

猜你喜欢

转载自blog.csdn.net/daily886/article/details/81129775
今日推荐