PHPUnit笔记

@date:2016-12-21 19:03:00

PHPUnit是一个面向PHP程序员的测试框架,这是一个xUnit的体系结构的单元测试框架。

复杂的项目,通过单元测试能够快速排查bug,有效减少bug的产生。简单的项目,使用php自带的var_dump()print_r()也能很方便的调试bug。

PHPUnit通过运行测试用例里的断言(例如判断返回结果不为空),检查代码是否符合预期。

安装 #

安装方式有两种。一种是使用phar包,一种是使用Composer。

1、使用phar包

下载地址 https://phpunit.de/

有三个版本:

PHPUnit 6.4 支持PHP 7.0, 和 PHP 7.1。(Current Stable Release)

PHPUnit 5.7 支持 PHP 5.6, PHP 7.0, 和 PHP 7.1。(Old Stable Release)

PHPUnit 4.8 支持PHP 5.3~5.6。(No Longer Supported)

运行方法:

# 通用
php phpunit.phar --version

# linux
chmod +x phpunit.phar
sudo mv phpunit.phar /usr/local/bin/phpunit
phpunit --version

可以查看版本号。

2、使用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/

配置PhpStorm使用PHPUnit #

1、点击File->Settings->Languages & Frameworks,点击php,设置PHP开发环境:

2、点击php->PHPUnitPHPUnit library里选中Path to phpunit.phar,指定路径,例如:D:\phpsetup\php\phpunit-5.7.4.phar

编写第一个测试用例 #

1、新建文件夹Testcase,编写SayHello.php:

<?php
 
class SayHello{
 
    public function printHello(){
        echo 'Hello';
        return 'Hello';

    }
}
?>

2、新建测试用例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个断言,没有失败。

这里注意的是:
1、所有以Test结尾的类均为测试用例;
2、所有以test开头的方法均是测试方法,会自动运行;
3、setUp是每个测试用例最先运行的方法,tearDown是每个测试用例最后运行的方法;
4、assertTrue用于判断结果是否为true。

如果用的PhpStorm,可以单击文件,右键Run SayHelloTest即可看到相同效果;也可以针对整个文件夹全部执行,选择文件夹Testcase右键Run Testcase即可。

ThinkPHP3.1集成PHPUnit #

集成 #

需要修改的地方:
1、复制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';

?>

需要使用绝对路径。

2、修改ThinkPHP/Lib/Core/App.class.php
run()方法里App::exec()改为:

(APP_PHPUNIT !== true) && App::exec();//支持phpunit

3、ThinkPHP/Core/Lib/Core/增加AjaxReturnEvent.class.php:

<?php

class AjaxReturnEvent extends Exception {
}

4、修改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方法都要修改。

5、修改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件事情:
1、支持phpunit测试模式;
2、防止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

1、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());
    }
 
}

2、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);
		}
    }
 
}


参考 #

1、开始使用 PHPUnit – PHP测试框架
http://phpunit.cn/getting-started.html
2、web3d/TPUnit: ThinkPHP PHPUnit框架集成
https://github.com/web3d/TPUnit/
3、[PHP]PHPUnit安装配置及样例 | CoinIdea的技术分享博客
http://blog.coinidea.com/web开发/php-1088.html
4、《xUnit Test Patterns》学习笔记系列 - CoderZh - 博客园
http://www.cnblogs.com/coderzh/archive/2010/01/23/xUnit-Test-Patterns.html

(未完待续)

Build by Loppo 0.6.14