Composer 安装PHPUnit
composer global require "phpunit/phpunit=5.5.*"
会将PHPUnit以全局的形式安装到电脑当中去
确保.bash_profile
文件包含命令路径
phpunit —help
可以查看命令
开始创建测试用例
首先要创建测试用例
use PHPUnit\Framework\TestCase;
class MyTest extend TestCase{
public function testArray(){
}
}
这样一个简单的测试用例就完成了需要注意的是方法名test开头
依赖关系
依赖关系需要注意的是:需要使用文档对依赖进行标注如:
在测试用例中:
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
@clone替代
@depends`。
标记多个依赖需要这样使用
/**
* @depends testProducerFirst
* @depends testProducerSecond
*/
数据供给器
定义数据供给器需要public方法返回应当是数组,另一种是实现Iterator接口,使用数据供给器的需要如下使用文档进行标注
/**
* @dataProvider additionProvider
*/
public function testAdd($a, $b, $expected)
{
$this->assertEquals($expected, $a + $b);
}
public function additionProvider()
{
return [
'adding zeros' => [0, 0, 0],
'zero plus one' => [0, 1, 1],
'one plus zero' => [1, 0, 1],
'one plus one' => [1, 1, 3]
];
}
依赖于数据供给器结合使用
/**
* @depends testProducerFirst
* @depends testProducerSecond
* @dataProvider provider
*/
public function testConsumer()
{
$this->assertEquals(
['provider1', 'first', 'second'],
func_get_args()
);
}
需要注意测试依赖的执行顺序
1.如果一个测试依赖于另外一个使用了数据供给器的测试,仅当被依赖的测试至少能在一组数据上成功时,依赖于它的测试才会运行。使用了数据供给器的测试,其运行结果是无法注入到依赖于此测试的其他测试中的。
2.所有的数据供给器方法的执行都是在对 setUpBeforeClass 静态方法的调用和第一次对 setUp 方法的调用之前完成的。因此,无法在数据供给器中使用创建于这两个方法内的变量。这是必须的,这样 PHPUnit 才能计算测试的总数量。
对异常进行测试
第一种方法:
class ExceptionTest extends TestCase
{
public function testException()
{
$this->expectException(InvalidArgumentException::class);
}
}
第二种方法:
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
}
除了 expectException()
方法外,还有 expectExceptionCode()
、expectExceptionMessage()
和 expectExceptionMessageRegExp()
方法可以用于为被测代码所抛出的异常建立预期。
或者,也可以用 @expectedException
、@expectedExceptionCode
、@expectedExceptionMessage
和 @expectedExceptionMessageRegExp
标注来为被测代码所抛出的异常建立预期。
对PHP错误进行测试
PHPUnit_Framework_Error_Notice 和 PHPUnit_Framework_Error_Warning 分别代表 PHP 通知与 PHP 警告。
/**
* @expectedException PHPUnit_Framework_Error
*/
public function testFailingInclude()
{
include 'not_existing_file.php';
}
对输出进行测试
public function testExpectFooActualFoo()
{
$this->expectOutputString('foo');
print 'foo';
}
其余的几种方法:
void expectOutputRegex(string $regularExpression)
设置输出预期为输出应当匹配正则表达式 $regularExpression
。
void expectOutputString(string $expectedString)
设置输出预期为输出应当与 $expectedString 字符串相等。
bool setOutputCallback(callable $callback)
设置回调函数,用来做诸如将实际输出规范化之类的动作。
需要注意的是:在严格模式下,本身产生输出的测试将会失败。
命令行测试执行器
phpunit 文件名
直接执行测试
PHPUnit 命令行工具输出一个字符来指示进展:
当测试成功时输出.
当测试方法运行过程中一个断言失败时输出F
当测试方法运行过程中产生一个错误时输出E
当测试被标记为有风险时输出R
当测试被跳过时输出S
当测试被标记为不完整或未实现时输出I
PHPUnit 区分 失败(failure)与错误(error)。失败指的是被违背了的 PHPUnit 断言,例如一个失败的 assertEquals()
调用。错误指的是意料之外的异常(exception)或 PHP 错误。这种差异已被证明在某些时候是非常有用的,因为错误往往比失败更容易修复。
setUp()与tearDown()方法
setUp方法是在测试方法之前开是调用的,一般用于创建属性对象做测试钱的准备工作.
tearDown()方法是在测试方法之后执行
用 XML 配置来编排测试套件
不一定非得用 —bootstrap参数来指定在测试执行前需要执行的文件,我们也可以采取编写phpunit.xml文件的形式来指定需要phpunit的参数,phpunit.xml需要放置在测试文件的目录下,phpunit命令会自动加载测试目录下的文件
未完成的测试与跳过的测试
未完成测试
public function testSomething()
{
// 可选:如果愿意,在这里随便测试点什么。
$this->assertTrue(true, '这应该已经是能正常工作的。');
// 在这里停止,并将此测试标记为未完成。
$this->markTestIncomplete(
'此测试目前尚未实现。'
);
}
运行结果如下
PHPUnit 5.6.0 by Sebastian Bergmann and contributors.
I
Time: 0 seconds, Memory: 3.95Mb
There was 1 incomplete test:
1) SampleTest::testSomething
This test has not been implemented yet.
/home/sb/SampleTest.php:12
OK, but incomplete or skipped tests!
Tests: 1, Assertions: 1, Incomplete: 1.
跳过该测试
<?php
use PHPUnit\Framework\TestCase;
/**
* @requires extension mysqli
*/
class DatabaseTest extends TestCase
{
/**
* @requires PHP 5.3
*/
public function testConnection()
{
// 测试要求有 mysqli 扩展,并且 PHP >= 5.3
}
// ... 所有其他要求有 mysqli 扩展的测试
}
或者是这样
<?php
use PHPUnit\Framework\TestCase;
class DatabaseTest extends TestCase
{
protected function setUp()
{
if (!extension_loaded('mysqli')) {
$this->markTestSkipped(
'MySQLi 扩展不可用。'
);
}
}
public function testConnection()
{
// ...
}
}
数据库测试
这里需要说明的是在采取框架开发的模式中,数据库的连接与其它想关的操作,都会被封装.因此对于框架的使用者不需要了解太多,因为框架里的代码坑定是经过相关详细的测试才会发布.
而对于原生的PHP开发者这可能是需要比较多的时间去学习与了解,这里暂时先不做详细的介绍.月末之前我会将本节进行补充说明.