PHPUnit测试框架


PHPUnit测试框架


引言

PHPUnit是什么?

  • 它是一款轻量级的PHP测试框架。

为什么要用PHPUnit?

  1. 可以通过命令操控测试脚本
  2. 可以测试性能
  3. 可以测试代码覆盖率
  4. 可以自动化的更新测试用例的参数数据
  5. 各种格式的日志

使用的步骤:

  1. 系统环境中安装 PHPUnit扩展(Phar档案包) 或 项目中Composer安装PHPUnit包
  2. 项目中加入单元测试
  3. 运行查看输出

这里可以翻阅下 https://ibaiyang.github.io/blog/php/2021/01/27/PHP-单元测试.html

这里记录了一些PHPUnit的测试实例,包含各设计模式,可以看一下 https://github.com/iBaiYang/PHPUnitTset

PHPUnit使用规则

1、一般被测试类的后面加上Test,比如要测试的类为Array,则测试用例的命名为ArrayTest。

2、测试类ArrayTest继承于PHPUnit_Framework_TestCase

3、测试方法必须为public权限,都是test开头,或者你也可以选择给其加注释@test来表明该函数为测试函数

4、通过断言方法来对实际值和预期值进行断言

安装

PHPUnit 的安装有两种方法,一是使用 Phar包,一种使用Composer。

Phar包相对来说现在用的少了,关于Phar包原理详细可以参看 https://ibaiyang.github.io/blog/php/2021/06/24/PHP-Phar使用.html

Composer会把包相关依赖都放到vendor目录下,使用起来方便,现在pecl拓展包更多选用Composer。

具体参见官网 https://phpunit.de/getting-started/phpunit-9.html

仓库 https://packagist.org/packages/phpunit/phpunit

Phar包方式

PHPUnit安装

要获取 PHPUnit,最简单的方法是下载 PHPUnit 的 PHP 档案包 (Phar), 它将 PHPUnit 所需要的所有必要组件(以及某些可选组件)捆绑在单个文件中:

要使用 PHP档案包(Phar)需要有 Phar 扩展。 如果你使用的是 PHP 5.3 或更高版本,那么Phar后缀文件是默认开启支持的,你不需要任何其他的安装就可以使用它。

如果启用了 Suhosin 扩展,需要在 php.ini 中允许执行 Phar:

suhosin.executor.include.whitelist = phar

Linux环境下使用PHPUnit有两种方式。

方式一、全局安装 Phar:

$ wget http://phar.phpunit.cn/phpunit-6.2.phar
$ chmod +x phpunit-6.2.phar
$ sudo mv phpunit-6.2.phar /usr/local/bin/phpunit
$ phpunit --version
PHPUnit x.y.z by Sebastian Bergmann and contributors.

方式二、直接使用下载的 Phar 文件:

$ wget http://phar.phpunit.cn/phpunit-6.2.phar
$ php phpunit-6.2.phar --version
PHPUnit x.y.z by Sebastian Bergmann and contributors.

PhpStorm配置

一般在Windows环境下,使用PhpStrom实现PHPUnit单元测试,可以如下操作。

在PhpStrom这个IDE中,配置PHPUnit。

第一步,点击 File->Settings->Languages & Frameworks->PHP 配置PHP版本 PHP (Language level)。

第二步,点击 File->Settings->Languages & Frameworks->PHP 配置命令行脚本程序 (CLI Interpreter)。

第三步,点击 File->Settings->Languages & Frameworks->PHP->Test Frameworks 配置 PHPUnit 的 包。

  • 在第一、第二步中要求你本地安装了PHP运行环境,如PHPStudy。
  • 在第三步中,需要先去 https://phar.phpunit.de/ 或 中文官网 http://www.phpunit.cn/ 下载 phpunit.phar 包, 移动到具体目录下,注意要与PHP版本适配。然后进行添加。

配置好后,在PhpStrom内置终端Terminal中运行看一下:

G:\www\test>php -v
PHP 7.4.3 (cli) (built: Feb 18 2020 17:29:57) ( NTS Visual C++ 2017 x64 )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies

G:\www\test>
G:\www\test>php G:\WorkSoft\phpuint\phpunit-8.5.9.phar --version
PHPUnit 8.5.9 by Sebastian Bergmann and contributors.


G:\www\test>

具体参考下: https://zhuanlan.zhihu.com/p/459902512 , https://www.likecs.com/show-840032.html , http://www.phpunit.cn/getting-started.html , https://baijiahao.baidu.com/s?id=1672356488789070116

配置好后,在项目中写好测试单元,然后在测试单元文件中鼠标右击选择Run,查看结果。

示例

在一个目录下新建两个文件,并写入代码。

src/Email.php

<?php
declare(strict_types=1);

final class Email
{
    private $email;

    private function __construct(string $email)
    {
        $this->ensureIsValidEmail($email);

        $this->email = $email;
    }

    public static function fromString(string $email): self
    {
        return new self($email);
    }

    public function __toString(): string
    {
        return $this->email;
    }

    private function ensureIsValidEmail(string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException(
                sprintf(
                    '"%s" is not a valid email address',
                    $email
                )
            );
        }
    }
}

tests/EmailTest.php

<?php
declare(strict_types=1);

require_once 'src/Email.php';

use PHPUnit\Framework\TestCase;

/**
 * @covers Email
 */
final class EmailTest extends TestCase
{
    public function testCanBeCreatedFromValidEmailAddress(): void
    {
        $this->assertInstanceOf(
            Email::class,
            Email::fromString('user@example.com')
        );
    }

    public function testCannotBeCreatedFromInvalidEmailAddress(): void
    {
        $this->expectException(InvalidArgumentException::class);

        Email::fromString('invalid');
    }

    public function testCanBeUsedAsString(): void
    {
        $this->assertEquals(
            'user@example.com',
            Email::fromString('user@example.com')
        );
    }
}

页面右击Run运行结果:

Testing started at 19:11 ...
G:\WorkSoft\phpstudy_pro\Extensions\php\php7.4.3nts\php.exe G:\WorkSoft\phpuint\phpunit-8.5.9.phar --no-configuration EmailTest G:\www\yii2_221104\EmailTest.php --teamcity
PHPUnit 8.5.9 by Sebastian Bergmann and contributors.

Warning:       Invocation with class name is deprecated



Time: 184 ms, Memory: 10.00 MB

OK (3 tests, 3 assertions)

Process finished with exit code 0

终端运行(注意要带上PHPUnit的Phar包位置),结果:

G:\www\yii2_221104>php G:\WorkSoft\phpuint\phpunit-8.5.9.phar tests/EmailTest.php
PHPUnit 8.5.9 by Sebastian Bergmann and contributors.

...                                                                 3 / 3 (100%)

Time: 222 ms, Memory: 10.00 MB

OK (3 tests, 3 assertions)

G:\www\yii2_221104>

Composer包方式

PHPUnit安装

有两种方式,一种是Composer全局安装,一种是项目内Composer安装。

全局安装:composer global require phpunit/phpunit=8.*

项目内安装:composer require phpunit/phpunit=8.*

示例

src/Email.php

<?php
declare(strict_types=1);

final class Email
{
    private $email;

    private function __construct(string $email)
    {
        $this->ensureIsValidEmail($email);

        $this->email = $email;
    }

    public static function fromString(string $email): self
    {
        return new self($email);
    }

    public function __toString(): string
    {
        return $this->email;
    }

    private function ensureIsValidEmail(string $email): void
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException(
                sprintf(
                    '"%s" is not a valid email address',
                    $email
                )
            );
        }
    }
}

tests/EmailTest.php

<?php
declare(strict_types=1);

require_once 'Email.php';

use PHPUnit\Framework\TestCase;

/**
 * @covers Email
 */
final class EmailTest extends TestCase
{
    public function testCanBeCreatedFromValidEmailAddress(): void
    {
        $this->assertInstanceOf(
            Email::class,
            Email::fromString('user@example.com')
        );
    }

    public function testCannotBeCreatedFromInvalidEmailAddress(): void
    {
        $this->expectException(InvalidArgumentException::class);

        Email::fromString('invalid');
    }

    public function testCanBeUsedAsString(): void
    {
        $this->assertEquals(
            'user@example.com',
            Email::fromString('user@example.com')
        );
    }
}

cmd命令行执行,如:

G:\www\PHPUnitTset>php vendor\bin\phpunit tests/EmailTest.php
PHPUnit 8.5.33 by Sebastian Bergmann and contributors.

...                                                                 3 / 3 (100%)

Time: 104 ms, Memory: 4.00 MB

OK (3 tests, 3 assertions)

G:\www\PHPUnitTset>

重点要注意 vendor\bin\phpunit 这个参数,和我们上面下载的Phar包一样,都是可执行文件参数。

我们换用Phar包试一下:

G:\www\PHPUnitTset>php G:\WorkSoft\phpuint\phpunit-8.5.9.phar tests/EmailTest.php
PHPUnit 8.5.9 by Sebastian Bergmann and contributors.

...                                                                 3 / 3 (100%)

Time: 199 ms, Memory: 10.00 MB

OK (3 tests, 3 assertions)

G:\www\PHPUnitTset>

发现完全可以互换。

Linux环境下也一样

Phar方式

➜ ./phpunit --bootstrap src/autoload.php tests
PHPUnit 9.0.0 by Sebastian Bergmann and contributors.

...                                                      3 / 3 (100%)

Time: 70 ms, Memory: 10.00MB

OK (3 tests, 3 assertions)

Composer方式

➜ ./vendor/bin/phpunit tests
PHPUnit 9.0.0 by Sebastian Bergmann and contributors.

...                                                       3 / 3 (100%)

Time: 70 ms, Memory: 10.00MB

OK (3 tests, 3 assertions)

PHPUnit_Framework_TestCase

\PHPUnit_Framework_TestCase\PHPUnit\Framework\TestCase 只是不同的版本,但是自PHPUnit 5.4起,建议使用TestCase。

看一个PHPUnit_Framework_TestCase的例子。

ArrayTest.php:

<?php

class ArrayTest extends PHPUnit_Framework_TestCase
{
    //测试用例运行前初始化
    public function setUp()
    {
    }

    //测试用例运行后执行
    public function tearDown()
    {
    }

    /**
     * @test
     */
    public function testArrayIsEmpty()
    {
        $fixture = array();

        // 断言数组$fixture中元素的数目是0。
        $this->assertEquals(0, sizeof($fixture));
    }

    /**
     * @test
     */
    public function testArrayHasKey()
    {
        $arr = array(
            'id' => 666,
            'name' => 'zhangsan',
        );
        //断言$arr是一个数组
        $this->assertTrue(is_array($arr));
        //断言数组$arr中含有索引id
        $this->assertArrayHasKey('id', $arr);
        //断言数组$arr中含有索引name
        $this->assertArrayHasKey('name', $arr);
    }

}

命令行启动测试用例:phpunit 测试文件名,此处为要测试ArrayTest.php文件

phpunit ArrayTest.php

PHPUnit 5.7.5 by Sebastian Bergmann and contributors.

.. 2 / 2 (100%)

Time: 138 ms, Memory: 3.25MB

OK (2 tests, 4 assertions)






参考资料

PHPUnit 中文网 http://www.phpunit.cn/

PHPUnit 手册 http://www.phpunit.cn/manual/current/zh_cn/index.html

PHPUnit简介及使用 https://www.cnblogs.com/rxbook/p/6763735.html


返回