本文目的
本文目的是收錄一些PHPUnit的有用技巧,這些技巧能夠為給PHPUnit單元測試帶來很多便利。本文將要介紹的技巧如下:
- 函數依賴測試
- 數據提供函數
- 異常測試
- 跳過忽略測試
- 自動生成測試框架
函數依賴測試
有時候,類中的函數有依賴,而且你的邏輯需要被依賴函數正確執行,此時,你可以通過phpunit的依賴標簽顯示的標明這種依賴關系,如果任意被依賴的函數執行失敗,那么依賴函數將會被自動跳過。如下所示代碼(dependenceDemo.cpp):
<?php
class DependanceDemo extends PHPUnit_Framework_TestCase
{
public function testOne()
{
echo "testOne\n";
$this->assertTrue(TRUE);
}
public function testTwo()
{
echo "testTwo\n";
$this->assertTrue(FALSE);
}
/**
* @depends testOne
* @depends testTwo
*/
public function testThree()
{
}
}
?>
上面的代碼執行結果如下圖:
可以看到,testThree依賴testOne和testTwo,但是testTwo失敗,所以testThree被跳過,使用S表示。
@depends標簽還可以依賴返回值。如下例子所示(paramDependence.php),
<?php
class DependanceDemo extends PHPUnit_Framework_TestCase
{
public function testOne()
{
$this->assertTrue(TRUE);
return "testOne";
}
public function testTwo()
{
$this->assertTrue(TRUE);
return "testTwo";
}
/**
* @depends testOne
* @depends testTwo
*/
public function testThree($param1, $param2)
{
echo 'First param: '.$param1."\n";
echo 'Second param: '.$param2."\n";
}
}
?>
上面代碼的執行結果如下:
值得注意的是,函數的順序與依賴標簽的數序一致。
數據提供函數
函數一般會有多組不同的輸入參數,如果每一組參數都寫一個測試函數,那么寫測試比較麻煩,如果能提供一種批量的參數輸入方法,那么測試代碼將會簡潔許多。好在,phpunit提供@dataProvider標簽,支持這種特性,看如下代碼(dataProviderDemo.php):
<?php
class DataTest extends PHPUnit_Framework_TestCase
{
/**
* @dataProvider provider
*/
public function testAdd($a, $b, $c)
{
$this->assertEquals($c, $a + $b);
}
public function provider()
{
return array(
array(0, 0, 0),
array(0, 1, 1),
array(1, 1, 1),
array(1, 2, 3)
);
}
}?>
上面的代碼輸出如下所示:
可以看到,函數testAdd遍歷了函數provider的返回的結果,並將他們作為參數,被@dataProvider標記的函數的唯一要求就是返回數組。
異常測試
PHPUnit提供三種方法測試異常,如下面代碼所示(exceptionsDemo.php):
<?php
class ExceptionsDemo extends PHPUnit_Framework_TestCase
{
/**
* @expectedException InvalidArgumentException
*/
public function testTagException()
{
throw new InvalidArgumentException;
}
public function testApiException()
{
$this->setExpectedException('InvalidArgumentException');
throw new InvalidArgumentException;
}
public function testTryException()
{
try
{
throw new InvalidArgumentException;
}
catch (InvalidArgumentException $expected)
{
return;
}
$this->fail('An expected exception has not been raised.');
}
}
?>
當然,這三種方法各有用處,效果等同,使用時看需要而定。
跳過忽略測試
在編寫單元測試過程中,有時候只寫出了測試方法名稱,沒有寫具體的測試內容。這樣,PHPUnit框架默認的認為此測試通過,這樣,我們很可能忘記了該測試方法還沒有實現,如果使用$this->fail(),只能表明該測試失敗,但是該測試並沒有失敗,令人誤解。所以,我們需要PHPUnit提供一組方法,使得可以跳過沒有實現的測試,並且給與正確的提示。PHPUnit提供下面這四個方法,幫助我們辦到這一點:
| 方法 |
意義 |
| void markTestSkipped() |
標記當前的測試被跳過,用“S”標記 |
| void markTestSkipped(string $message) |
標記當前的測試被跳過,用“S”標記,並且輸出一段示消息 |
| void markTestIncomplete |
標記當前的測試不完全,用“I”標記 |
| void markTestIncomplete(string $message) |
標記當前的測試不完全,用“I”標記,並且輸出一段提示消息 |
下面的代碼演示了上面四個方法的使用(SIMarkDemo.php):
<?php
class SkipIncompleteMarkDemo extends PHPUnit_Framework_TestCase
{
public function testSkipped()
{
$this->markTestSkipped();
}
public function testSkippedWithMessage()
{
$this->markTestSkipped("this is a skipped test.");
}
public function testIncomplete()
{
$this->markTestIncomplete();
}
public function testIncompleteWithMessage()
{
$this->markTestIncomplete("this is a incomplete test.");
}
}
?>
輸出結果如下
自動生成測試框架
在編寫單元測試的時候,你會發現有些代碼都是千篇一律的,比如testXXXX(){…..},所以基於這種考慮,PHPUnit提供了生成測試框架的命令。該命令可以給為被測試的類中的每一個方法生成一個默認的測試方法,該方法使用markTestIncomplete標記。
如下圖面的代碼表示的類,
<?php
class Calculator
{
public function add($a, $b)
{
return $a + $b;
}
public function minus($a, $b)
{
return $a - $b;
}
}
?>
使用如下命令:
將會生成一個類CalculatorTest.php,內容如下:
<?php
require_once 'PHPUnit/Framework.php';
require_once '/home/bourneli/test/UnitTestDemo/PHPUnitFeatures/Calculator.php';
/**
* Test class for Calculator.
* Generated by PHPUnit on 2011-05-24 at 20:54:59.
*/
class CalculatorTest extends PHPUnit_Framework_TestCase
{
/**
* @var Calculator
*/
protected $object;
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp()
{
$this->object = new Calculator;
}
/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*/
protected function tearDown()
{
}
/**
* @todo Implement testAdd().
*/
public function testAdd()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
/**
* @todo Implement testMinus().
*/
public function testMinus()
{
// Remove the following lines when you implement this test.
$this->markTestIncomplete(
'This test has not been implemented yet.'
);
}
}
?>
可以看到,該框架還是比較完整的,生成了setUp,tearDown函數,還為每一個函數生成了一個測試方法。當然,phpunit還提供替他框架函數,如果想要了解更多,可以參見參考文檔中的鏈接。
參考文檔


![clip_image002[5] clip_image002[5]](/image/aHR0cHM6Ly9pbWFnZXMuY25ibG9ncy5jb20vY25ibG9nc19jb20vYm91cm5lbGkvMjAxMjA5LzIwMTIwOTA4MjAzMTQ0OTMxNC5qcGc=.png)
![clip_image002[9] clip_image002[9]](/image/aHR0cHM6Ly9pbWFnZXMuY25ibG9ncy5jb20vY25ibG9nc19jb20vYm91cm5lbGkvMjAxMjA5LzIwMTIwOTA4MjAzMTQ1OTI0Ny5qcGc=.png)
![clip_image002[11] clip_image002[11]](/image/aHR0cHM6Ly9pbWFnZXMuY25ibG9ncy5jb20vY25ibG9nc19jb20vYm91cm5lbGkvMjAxMjA5LzIwMTIwOTA4MjAzMTQ1NDUxNC5qcGc=.png)
![clip_image002[13] clip_image002[13]](/image/aHR0cHM6Ly9pbWFnZXMuY25ibG9ncy5jb20vY25ibG9nc19jb20vYm91cm5lbGkvMjAxMjA5LzIwMTIwOTA4MjAzMTQ2Njk1Ni5qcGc=.png)