PHP单元测试PHPUnit
简介
# PHPUnit的依赖
- dom,PHP默认启用
- json,PHP默认启用
- pcre,PHP默认启用
- reflection,PHP默认启用
- spl,PHP默认启用
- tokenizer,PHP默认启用,生成代码覆盖率测试报告用到
- xdebug,需要自己安装,生成代码覆盖率测试报告用到
- xmlwriter,PHP默认启用,生成XML格式的报告用到
检查PHP是否启用了这些模块可以使用如下命令
php -m | grep '模块名称'
PHPUnit的安装
PHP档案包方式
wget https://phar.phpunit.de/phpunit.phar # 下载档案包
chmod +x phpunit.phar # 赋可执行权限
sudo mv phpunit.phar /usr/local/bin/phpunit
phpunit --version # 查看PHPUnit版本
Composer方式
Composer使用参考https://getcomposer.org/
composer文件如下
{
"require-dev": {
"phpunit/phpunit": "5.0.*"
}
}
编写PHPUnit测试
惯例和基本步骤
- 针对类Class的测试写在类ClassTest中。
- ClassTest通常继承自PHPUnit_Framework_TestCase。
- 测试都是命名为test*的公用方法(也可以在放的文档注释块中使用@test标注将其标记未测试方法)。
- 在测试方法内,类似于assertEquals()这样的断言方法用来对实际值与预期值的匹配做出断言
举个例子:
<?php
class HelloWolrdTest extends PHPUnit_Framework_TestCase
{
public function testString()
{
$string = 'Hello, World';
$this->assertEquals('Hello, World', $string);
$this->assertNotEquals('Hello,World', $string);
}
public function testAarry()
{
$arr = array();
$this->assertEmpty($arr);
//$this->assertArrayHasKey('hello', $arr);
$arr['hello'] = 'world';
//$this->assertEmpty($arr);
$this->assertArrayHasKey('hello', $arr);
}
}
执行测试命令
phpunit HelloWorldTest
结果
PHPUnit 4.8.24 by Sebastian Bergmann and contributors.
..
Time: 103 ms, Memory: 12.50Mb
OK (2 tests, 4 assertions)
依赖
@depends表示依赖关系
<?php class DependenceTest extends PHPUnit_Framework_TestCase
{
public function testEmpty()
{
$arr = array();
$this->assertEmpty($arr);
return $arr;
}
/**
* @depends testEmpty
*/
public function testPush(array $arr)
{
array_push($arr, 'foo');
$this->assertEquals('foo', $arr[count($arr) - 1]);
$this->assertNotEmpty($arr);
return $arr;
}
/**
* @depends testPush
*/
public function testPop(array $arr)
{
$this->assertEquals('foo', array_pop($arr));
$this->assertEmpty($arr);
}
public function testOne()
{
$this->assertTrue(false);
}
/*
* @depends testOne
*/
public function testTwo()
{
$this->assertTrue(1);
}
public function testProducerFirst()
{
$this->assertTrue(true);
return 'first';
}
public function testProducerSecond()
{
$this->assertTrue(true);
return 'second';
}
/**
* @depends testProducerFirst
* @depends testProducerSecond
*/
public function testOneConsumer()
{
$this->assertEquals(
array('first', 'second'),
func_get_args()
);
}
/**
* @depends testProducerSecond
* @depends testProducerFirst
*/
public function testTwoConsumer()
{
$this->assertEquals(
array('first', 'second'),
func_get_args()
);
}
}
数据提供器
@dataProvider表示数据提供器
<?php
class DataProviderTest extends PHPUnit_Framework_TestCase
{
public function getTestAddData()
{
return array(
array(0, 0, 0),
array(0, 1, 1),
array(1, 1, 2),
array(2, 2, 5),
);
}
/**
* @dataProvider getTestAddData
*/
public function testAdd($op1, $op2, $sum)
{
$this->assertEquals($sum, $op1 + $op2);
}
/**
* @dataProvider getTestMulData
*/
public function testMul($op1, $op2, $mul)
{
$this->assertEquals($mul, $op1 * $op2);
}
public function getTestMulData()
{
return array(
array(1, 1, 1),
array(2, 3, 6),
array(3, 3, 8),
);
}
}
对异常进行测试
@expectedException表示程序抛出异常
@expectedException可以结合@expectedExceptionCode、@expectedExceptionMessage、@expectedExceptionMessageRegExp使用
<?php
class ExceptionTest extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testException()
{
throw new InvalidArgumentException('', 0);
//throw new Exception('', 0);
}
/**
* @expectedException Exception
* @expectedExceptionCode 404
*/
public function testExceptionCode()
{
throw new Exception('exception', 404);
//throw new Exception('exception', 30);
}
/**
* @expectedException Exception
* @expectedExceptionMessage test
*/
public function testExceptionMessage()
{
throw new Exception('test', 0);
//throw new Exception('abcdefg', 0);
}
/**
* @expectedException Exception
* @expectedExceptionMessageRegExp /[a-z]+/
*/
public function testExceptionMessageRegExp()
{
throw new Exception('test', 0);
//throw new Exception('TEST', 0);
}
public function testOne()
{
$this->assertEquals(1, 1);
}
}
对输出进行测试
expectOutputString方法可以测试程序的输出
<?php
class OutputTest extends PHPUnit_Framework_TestCase
{
public function testOutputOne()
{
$this->expectOutputString('foo');
print 'test';
}
public function testOutputTwo()
{
$this->expectOutputString('foo');
print 'foo';
}
}
PHPUnit的输出
先看一个demo
<?php
class SummaryTest extends PHPUnit_Framework_TestCase
{
public function testSuccess()
{
$this->assertEquals(1, 1);
}
public function testFail()
{
$this->assertEquals(2, 1);
}
public function testException()
{
throw new Exception('', 0);
}
/*
* @depends testThree
*/
public function testSkip()
{
$this->assertEquals(2, 1);
}
}
执行命令
phpunit SummaryTest
输出结果如下
PHPUnit 4.8.24 by Sebastian Bergmann and contributors.
.FEF
Time: 96 ms, Memory: 12.00Mb
There was 1 error:
1) SummaryTest::testException
Exception:
/Users/kenneth/codes/php/phpunit/SummaryTest.php:18
--
There were 2 failures:
1) SummaryTest::testFail
Failed asserting that 1 matches expected 2.
/Users/kenneth/codes/php/phpunit/SummaryTest.php:13
2) SummaryTest::testSkip
Failed asserting that 1 matches expected 2.
/Users/kenneth/codes/php/phpunit/SummaryTest.php:26
FAILURES!
Tests: 4, Assertions: 3, Errors: 1, Failures: 2.
看输出第二行,有.FEF等,分表表示如下信息:
- . :表示断言通过
- F:表示断言失败
- E:表示测试过程中抛出一个错误
- R:表示测试被标记为有风险
- S:表示测试被跳过
- I :表示测试被标记未不完整或未实现