现在的位置: 首页 > 综合 > 正文

PHPUnit单元测试系列二 — 如何开展单测

2013年09月19日 ⁄ 综合 ⁄ 共 2364字 ⁄ 字号 评论关闭

虽然大家都说TDD,都有美好的幻想说,我们先写测试用例,然后再写实际代码。不过,现实中,我目前还没接触过这样的团队(真希望以后,能够到这种团队,很认真的TDD开发,有这样团队的记得联系我哈~留言就可以了~),大部分的人都是已经刚开发好了,然后,才加入单元测试的。

而且,大部分的情况都是,老大要求做单元测试,或者,对应的QA做单元测试。我待过3个团队,都是先开发代码,然后老大要求做单元测试,所以才这么弄的。我不喜欢,这种需要其他人来催促,才做单元测试的团队。

针对这种先有代码,后要弄单元测试的,困难程度和RD的素质成反比。RD素质越高,代码质量越好,单测越好写。按照我的经历,这个过程中,有一些困难:1.有一些依赖特别难解除;2.数据库;3.如何mock一些场景,比如,Yii框架中的组件,要么mock很困难,要么mock这个method,就会影响其他的method。

废话不多说,直接入正题,如何在已有代码的情况下,开展单测。

一、确定框架

不适用框架的场景:

PHP这么被互联网公司广泛使用的原因,在于简单还有其框架也很简单。虽然,我们可以不使用任何框架,就能够开发。这种情况也有,单测也很好写,就是直接加载,然后,调用方法,最后$this->assertEquals();判断就完事了。而且,这种代码中,要测试的对象也很明确。

对于使用框架的场景:

有了框架之后,method就多了,茫茫多啊。什么Controller、model、components的,一堆一堆的。有的人,雄心壮志,要测试所有的method。基本是不大可能对所有的method都做测试的,除非你的团队其他事情都不做,就做单元测试。

我们通过合理选择"高层"的测试对象,然后,通过行覆盖来搞定其他的method。基本上,都是controller调用model或者components的东西,所以大部分情况下,我们都是测试Controller或者是action之类的。对于其他的,我们就要分开对待了,如果是很重要的method,我们可以单独写测试用例,不然,我们都不需要考虑这个。

确定要测试的对象之后,我们就可以开始了。就以Yii框架为例,这里有Yii框架的demo,不过,它的case不是很好,我准备改进改进。这里是Yii框架的例子,不熟悉的先看看。Yii框架给了四个demo,分别是hello
world,
Hangman Game
PhonebookYii
Blog
. 然后,我会写根据这个来写测试用例,任何的代码,我都会在我本地跑通,欢迎大家下载查阅。

先从Hello world入手,Yii框架hello world的代码,只有简单的一个Index.php和SiteController.php。

1、加载框架

加载框架的代码和index.php的代码差不多一样,只不过,我们把run();给去掉了,因为我们调用controller的方式是手工的。代码如下:

<?php
// include Yii bootstrap file
require_once(dirname(__FILE__).'/../../framework/yii.php');

// create a Web application instance and run
Yii::createWebApplication();

function runController($strController, $isAjax = true){
    if($isAjax){
        $_SERVER['HTTP_X_REQUESTED_WITH']='XMLHttpRequest';
    }
    $_SERVER['REQUEST_URI'] = $strController;
    $route = Yii::app()->getUrlManager()->parseUrl(new CHttpRequest());

    list($controller, $action) = Yii::app()->createController($route);
    $controller->init();
    return $controller->run($action);
}
?>

这里要注意,我们多加了个runController的函数,这个函数就是用于我们手工的去调用controller。

这样,我们就完成我们的bootstrap文件了。因为这个例子很简单,我们就可以开始写CASE了。

2.编写Hello的测试用例

我们要测试的内容就是,打印出来的语句是否为Hello World.

<?php
require_once(dirname(__FILE__).'/../index-test.php');

class siteControllerTest extends PHPUnit_Framework_TestCase{
    public function setup(){
    }

    public function testHelloworld(){
        ob_start();
        $res = runController('site/index');
        $echoRes = ob_get_contents();
        $this->assertEquals($echoRes, 'Hello World');

    }
}
?>

在这个case里,我们首先加载我们第一步写好的启动文件,然后使用PHPUnit框架,继承其TestCase的基础类。然后,在实际的测试代码testHelloworld中,我们使用ob_start和ob_get_contents来获取echo的结果,最后进行比对。这就是最简单的Hello world单元测试。

下面附上我自己运行的结果:

接下来,我们就要弄剩下的DEMOS了。

因为平时要上班,只能空闲时间写,如果大家有问题,欢迎提出。代码等我写完了,就一起上传上来。

抱歉!评论已关闭.