在開發程式時,為了確保程式的正確性,一定都會使用到單元測試。但撰寫單元測試的方法因人而異,有時候土炮起來寫測試程式的時間還比正常開發的時間還要長,這時候就必須找個適合的工具幫忙處理測試的問題。PHPUnit就是負責解決這樣的狀況。
安裝 (可參考 安裝文件)
wget https://phar.phpunit.de/phpunit.phar chmod +x phpunit.phar mv phpunit.phar /usr/local/bin/phpunit
PS:為了避免程式找不到PHPUnit的class,最好是用PHP的get_include_path()檢查path是不是有引入PEAR的路徑(如果沒有可以到php.ini新增)
撰寫 PHPUnit 測試程式
首先建立一個簡單的程式,負責加總傳入的n到m總合
Math.php
class Math {
function sum($min, $max){
$total = 0;
for($i = $min; $i <= $max; $i++){
$total += $i;
}
return $total;
}
}
接著撰寫PHPUnit測試程式
MathTest.php
//引入要測試的程式
require "Math.php";
class MathTest extends PHPUnit_Framework_TestCase
{
//測試function的命名為test + function name
public function testsum()
{
//assertEquals為判斷值是否相同,55為正確的結果,比對傳入sum(1,10)時,是否傳出55
$this -> assertEquals(55,Math::sum(1,10));
$this -> assertEquals(5050,Math::sum(1,100));
}
}
寫好測試程式之後,就可以透過指令測試
phpunit MathTest.php #如果正確的話,應該會輸出OK (1 test, 2 assertion),代表一組測試二筆測資
Data Provider
上面的例子也可以改成以 Data Provider的方式餵資料進去,這樣一來就不必寫很多次assertEquals
MathTest.php
//引入要測試的程式
require "Math.php";
class MathTest extends PHPUnit_Framework_TestCase
{
//利用PHPUnit @dataProvider annotation來引用自訂的DataProvider
/**
* @dataProvider sumDataProvider
*/
public function testsum($expected, $min, $max)
{
$this -> assertEquals($expected,Math::sum($min,$max));
}
public function sumDataProvider(){
return array(
array(55,1,10),
array(5050,1,100),
);
}
}
PS:Data Provider提供的資料都會被當成一組test,所以測試後應該會出現OK (2 tests, 2 assertions)
setUP、tearDown
setUP和tearDown是執行PHPUnit時預設執行的函式,主要是用來初始化設定及結束設定用的,執行順序為:setUp、test*、tearDown
MathTest.php
require "Math.php";
class MathTest extends PHPUnit_Framework_TestCase
{
protected $_object;
protected function setUp(){
//開始測試時產生物件
$this -> _object = new Math();
}
/**
* @dataProvider sumDataProvider
*/
public function testsum($expected, $min, $max)
{
$this -> assertEquals($expected,$this -> _object -> sum($min,$max));
}
public function sumDataProvider(){
return array(
array(55,1,10),
array(5050,1,100),
);
}
protected function tearDown(){
//測試結束時結束物件
$this -> _object = null;
}
}
上面的範例執行順序為:1.setUp、testsum(55,1,10)、tearDown 2.setUp、testsum(5050,1,100)、tearDown
測試錯誤:expectedException
在某些時候必須去測試錯誤,因為當使用者輸入錯的資料時,程式沒有噴出Exception,這樣的程式也是有問題的,PHPUnit可以透expectedException annotation 來測試預期的錯誤(要傳出正確的Exception才算測試成功)
ExceptionTest.php
class ExceptionTest extends PHPUnit_Framework_TestCase{
/**
* @expectedException BadFunctionCallException
*/
public function testException(){
try {
//dosomething
} catch(BadFunctionCallException $e){
throw $e;
}
}
}
套件測試:Suite
若一個專案有多個測試時,可以透過Suite將所有測試程式包成套件測試
AllTest.php
require "ExceptionTest.php";
require "MathTest.php";
class AllTest extends PHPUnit_Framework_TestCase
{
public static function suite(){
$suite = new PHPUnit_Framework_TestSuite('SuiteName');
//加入class名稱
$suite -> addTestSuite('ExceptionTest');
$suite -> addTestSuite('MathTest');
return $suite;
}
}
也可以將多個套件再包裝成一組套件
All2Test.php
require "AllTest.php";
class All2Test extends PHPUnit_Framework_TestCase
{
public static function suite(){
$suite = new PHPUnit_Framework_TestSuite('SuiteName');
//加入套件
$suite -> addTest(AllTest::suite());
return $suite;
}
}
phpunit.xml
除了使用程式包裝成套件之外,也可以透過phpunit.xml來完成
phpunit.xml
<!-- colors為true可以讓測試結果加上顏色方塊,bootstrap可以自行定義init程式(例如define一些變數) -->
<phpunit colors="true" bootstrap="init.php">
<testsuite name="TestSuite">
<directory>./tests</directory>
</testsuite>
</phpunit>
測試
#使用phpunit指令,預設會按照phpunit.xml執行 phpunit #指定執行其他檔名的xml phpunit -c xxx.xml #也可以在phpunit.xml同一層目錄下直接使用資料夾名稱 phpunit <directory>
另外要注意,phpunit.xml的目錄是判斷 xxxTest的程式才會執行,所以命名時要特別注意一下
相關資料可以參考 PHPUnit文件