引言
PHPUnit是什么?
- 它是一款轻量级的PHP测试框架。
为什么要用PHPUnit?
- 可以通过命令操控测试脚本
- 可以测试性能
- 可以测试代码覆盖率
- 可以自动化的更新测试用例的参数数据
- 各种格式的日志
使用的步骤:
- 系统环境中安装 PHPUnit扩展(Phar档案包) 或 项目中Composer安装PHPUnit包
- 项目中加入单元测试
- 运行查看输出
这里可以翻阅下 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