PHPUnit是一個面向PHP程序員的測試框架,這是一個xUnit的體系結構的單元測試框架。php
複雜的項目,經過單元測試可以快速排查bug,有效減小bug的產生。簡單的項目,使用php自帶的var_dump()
、print_r()
也能很方便的調試bug。html
PHPUnit經過運行測試用例裏的斷言(例如判斷返回結果不爲空),檢查代碼是否符合預期。linux
安裝方式有兩種。一種是使用phar包,一種是使用Composer。git
一、使用phar包程序員
下載地址 https://phpunit.de/github
有三個版本:web
PHPUnit 6.4 支持PHP 7.0, 和 PHP 7.1。(Current Stable Release)ajax
PHPUnit 5.7 支持 PHP 5.6, PHP 7.0, 和 PHP 7.1。(Old Stable Release)thinkphp
PHPUnit 4.8 支持PHP 5.3~5.6。(No Longer Supported)json
運行方法:
# 通用 php phpunit.phar --version # linux chmod +x phpunit.phar sudo mv phpunit.phar /usr/local/bin/phpunit phpunit --version
能夠查看版本號。
二、使用Composer
若是用 Composer 來管理項目的依賴關係,只要在項目的composer.json 文件中簡單地加上對 phpunit/phpunit
的依賴關係便可。下面是一個最小化的 composer.json
文件的例子,只定義了一個對 PHPUnit 5.7
的開發時依賴:
{ "require-dev": { "phpunit/phpunit": "5.5.*" } }
要經過 Composer
完成系統級的安裝,能夠運行:
composer global require "phpunit/phpunit=5.5.*"
請確保 path 變量中包含有 ~/.composer/vendor/bin/
。
一、點擊File->Settings->Languages & Frameworks
,點擊php
,設置PHP開發環境:
二、點擊php->PHPUnit
,PHPUnit library
裏選中Path to phpunit.phar
,指定路徑,例如:D:\phpsetup\php\phpunit-5.7.4.phar
:
一、新建文件夾Testcase
,編寫SayHello.php:
<?php class SayHello{ public function printHello(){ echo 'Hello'; return 'Hello'; } } ?>
二、新建測試用例SayHelloTest.php
<?php require_once 'SayHello.php'; class SayHelloTest extends PHPUnit_Framework_TestCase { public function setUp(){ } public function tearDown(){ } public function testConnectionIsValid(){ $hi = new SayHello(); $this->assertTrue($hi->printHello() == 'Hello'); } }
編寫完成後,切換到phpunit.phar所在目錄命令行執行:
$ php phpunit.phar Testcase/SayHelloTest.php
輸出結果:
PHPUnit 5.7.4 by Sebastian Bergmann and contributors. . 1 / 1 (100%)Hello Time: 130 ms, Memory: 10.00MB OK (1 test, 1 assertion)
結果代表:
測試經過,1個測試方法,1個斷言,沒有失敗。
這裏注意的是:
一、全部以Test結尾的類均爲測試用例;
二、全部以test開頭的方法均是測試方法,會自動運行;
三、setUp是每一個測試用例最早運行的方法,tearDown是每一個測試用例最後運行的方法;
四、assertTrue
用於判斷結果是否爲true。
若是用的PhpStorm,能夠單擊文件,右鍵Run SayHelloTest
便可看到相同效果;也能夠針對整個文件夾所有執行,選擇文件夾Testcase
右鍵Run Testcase
便可。
須要修改的地方:
一、複製index.php爲phpunit.php,內容增長:
define('APP_PHPUNIT', true);
示例:
<?php define('APP_DEBUG', true); header("Content-type: text/html; charset=utf-8"); //define('APP_PATH', './'); define('APP_PATH', __DIR__ .'/'); define('APP_PHPUNIT', true); require APP_PATH .'Core/ThinkPHP.php'; ?>
須要使用絕對路徑。
二、修改ThinkPHP/Lib/Core/App.class.php
:
將run()
方法裏App::exec()
改成:
(APP_PHPUNIT !== true) && App::exec();//支持phpunit
三、ThinkPHP/Core/Lib/Core/
增長AjaxReturnEvent.class.php
:
<?php class AjaxReturnEvent extends Exception { }
四、修改ThinkPHP/Common/runtime.php
:
將2處
CORE_PATH.'Core/Think.class.php', CORE_PATH.'Core/ThinkException.class.php', // 異常處理類 CORE_PATH.'Core/Behavior.class.php',
改成:
CORE_PATH.'Core/Think.class.php', CORE_PATH.'Core/ThinkException.class.php', // 異常處理類 CORE_PATH.'Core/Behavior.class.php', CORE_PATH.'Core/AjaxReturnEvent.class.php',
記得是2處。load_runtime_file和build_runtime_cache方法都要修改。
五、修改ThinkPHP/Lib/Core/Action.class.php
裏ajaxReturn方法:
switch (strtoupper($type)){ case 'JSON' : // 返回JSON數據格式到客戶端 包含狀態信息 header('Content-Type:application/json; charset=utf-8'); if(APP_PHPUNIT === true){throw new AjaxReturnEvent(json_encode($data)); return;}//以支持phpunit捕獲結果 exit(json_encode($data)); case 'XML' : // 返回xml格式數據 header('Content-Type:text/xml; charset=utf-8'); if(APP_PHPUNIT === true){throw new AjaxReturnEvent(xml_encode($data)); return;}//以支持phpunit捕獲結果 exit(xml_encode($data)); case 'JSONP': // 返回JSON數據格式到客戶端 包含狀態信息 header('Content-Type:application/json; charset=utf-8'); $handler = isset($_GET[C('VAR_JSONP_HANDLER')]) ? $_GET[C('VAR_JSONP_HANDLER')] : C('DEFAULT_JSONP_HANDLER'); if(APP_PHPUNIT === true){throw new AjaxReturnEvent($handler.'('.json_encode($data).');'); return;}//以支持phpunit捕獲結果 exit($handler.'('.json_encode($data).');'); case 'EVAL' : // 返回可執行的js腳本 header('Content-Type:text/html; charset=utf-8'); if(APP_PHPUNIT === true){throw new AjaxReturnEvent($data); return;}//以支持phpunit捕獲結果 exit($data); default : // 用於擴展其餘返回格式數據 tag('ajax_return',$data); }
主要作了2件事情:
一、支持phpunit測試模式;
二、防止ajaxReturn裏的exit結束了程序。
目錄結構(示例程序採用了模塊分組):
--example |--Common |--Conf |--ThinkPHP |--Lib |--Action | |--Weixin | |--Api | |--UserAction.class.php |--Model |--Runtime |--Testcase |--Weixin |--Api |--UserAction.class.php |--Tpl |--vendor |--index.php |--phpunit.php
一、Model測試
<?php define('TEST_PATH', dirname(dirname(__FILE__))); require TEST_PATH .'/../phpunit.php'; class OrderTest extends PHPUnit_Framework_TestCase { public function testGetBillRule(){ $order_model = D('Orders'); $this->assertTrue(is_object($order_model) == true); $this->assertNotEmpty($order_model->getBillRule()); } }
二、Api測試
<?php define('TEST_APP', 'Api'); define('TEST_PATH', dirname(dirname(__FILE__))); require TEST_PATH .'/../phpunit.php'; class OrderTest extends PHPUnit_Framework_TestCase { public function setUp() { //自動加載 spl_autoload_register (function ( $class ) { include APP_PATH . 'Lib/Action/'.TEST_APP.'/' . $class . '.class.php' ; }); } public function tearDown(){ } public function testModule(){ $obj = new OrderAction(); $this->assertTrue(is_array($obj->getBillRule()) == true); } public function testApi(){ try{ $obj = new OrderAction(); $obj->getBillRule(); //因爲TP裏的ajaxReturn會使用exit結束程序,這裏使用異常來獲得返回的內容 }catch(AjaxReturnEvent $e){ $res = json_decode($e->getMessage(), treu); $this->assertNotEmpty($res); } } }
一、開始使用 PHPUnit – PHP測試框架
http://phpunit.cn/getting-started.html
二、web3d/TPUnit: ThinkPHP PHPUnit框架集成
https://github.com/web3d/TPUnit/
三、[PHP]PHPUnit安裝配置及樣例 | CoinIdea的技術分享博客
http://blog.coinidea.com/web%e5%bc%80%e5%8f%91/php-1088.html
四、《xUnit Test Patterns》學習筆記系列 - CoderZh - 博客園
http://www.cnblogs.com/coderzh/archive/2010/01/23/xUnit-Test-Patterns.html
(未完待續)