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
(未完待续)