我在yii2.0里自动生成的protected/tests/unit下建立了UserController_Test.php,
代码见下:
class UserController_Test extends CTestCase {
public $userController;
protected function setUp() {
parent::setUp();
$this->userController = new UserController_Mock(); //测试替身
}
public function testCreate() {
//step 1. 构建
$fields = array(
'face_url' => '',
'nick_name' => 'tongtong',
'real_name' => 'denglitong',
'phone' => '15622753418',
'password' => 'root',
'department_id' => 1,
'school_id' => 1,
);
$this->userController->setAttributes($fields);
//step 2. 执行
$result = $this->userController->actionCreate();
//step 3. 验证
print_r($result);
}
} class UserController_Mock extends UserController {
public function setAttributes($array) {
$this->object = (object)$array;
}
}
在目录 /protected/tests/ 下在终端运行 phpunit --bootstrap bootstrap.php unit/UserController_Test.php 提示PHP Warning: include(PHPUnit_Extensions_Database_TestCase.php): failed to open stream: No such file or directory in /var/www/html/weidouapp/framework/YiiBase.php on line 448
经过一番努力,终于解决了Yii2.0单元测试这个棘手的问题!下面是我的一些解决过程,和大家一起学习了(想要看简要解决步骤的直接看第9点)。
-
考虑到和团队其他成员的协作,一开始我是打算在Windows下装phpunit的,下载go-pear.phar装好pear后在命令行下添加包老是出错,最后装上了phpunit,但跑起来的时候还是出错,经过几番折腾装了几次仍然失败之后,决定放弃windows转到Ubuntu下开发。
-
在Ubuntu下装phpunit只需要在终端输入sudo apt-get install phpunit就可以装好了,Yii框架使用了selenium来测试所以还需要安装selenium,sudo apt-get install phpunit-selenium; 装好后然后就去protected/tests/unit下写单元测试,然后在终端的时候出现了PHPUnit_Extensions_Database_TestCase.php not found这个错误,百度Google一番好像是需要先安装phpunit/DbUnit,于是我去装phpunit/DbUnit,用pear安装phpunit/DbUnit的时候总是提示no release found,或者是http://pear.phpunit.de/dbunit not found,找不到安装包,于是我怀疑我的Ubuntukylin14.04 LTS的源是不是没有更新到最新,于是先去修改源,然而结果还是一样,所以,继续Google,,(困扰了几天了,然而项目在那里,客户要求要有单元测试报告,如果这个解决不了后面的推进不了。。。)
-
于是我沉住气继续Google,发现了一个链接phpunit/dbunit - Packagist,上面写的是安装dbunit用的是这一句 composer require phpunit/dbunit,于是我又得先安装composer,好了,安装composer用这两句搞定 curl -sS https://getcomposer.org/installer | php mv composer.phar /usr/local/bin/composer,是全局安装。安装好之后接着安装了phpunit/dbunit,这次安装很顺利,以为就要成功了,然而安装之后phpunit单元测试仍然报错找不到PHPUnit_Extension_Database_TestCase.php,(真是百思不得姐啊)。。
-
还是上面那个链接phpunit/dbunit - Packagist,发现了博主github!于是点进去,看到博主github上面的这个dbunit代码包sebastianbergmann/dbunit · GitHub,结合前面的报错加上过程中Google看到有些例子的写法是 require '/Extensions/Database/TestCase.php'; class abcTest extends PHPUnit_Extensions_Database_TestCase { } 于是想到可能在PHPUnit下面在Extensions里有Database这个模块就可以了?(sudo apt-get install phpunit安装的PHPUnit的Extensions目录下是没有Database这个扩展包的),于是我怀着试一试的心态下载了下来,然后拷贝到/usr/share/php/PHPUnit/Extensions目录下,再去项目protected/tests目录下运行 phpunit unit/UserController_Test.php,这一次之前的错误PHPUnit_Extension_Database_TestCase.php not found 解决了,然而又出现了一个新的bug...PHPUnit_Extension_Database_TestCaseTrait not found,于是我再次沉住气,打开了/Extension/Database的目录看代码(其实此刻我的心情是呵呵哒的。。。),打开TestCase.php,TestCaseTrait.php,在TestCase.php 有一句 use PHPUnit_Extensions_TestCaseTrait,应该就是在这一句报的错,于是再去打开Autoload.php,里面有一个从类名到文件名的映射数组,找到了 "phpunit_extensions_database_testcase" => "/Extensions/Database/TestCase.php"这一句,唯独就是没有"phpunit_extensions_database_testcase_trait" => "/Extensions/Database/TestCaseTrait.php"这一句,我在Autoload.php添加了这一句之后再去测试phpunit unit/UserController_Test.php,之前的报错都消失了!好开心,终于快要看到胜利的曙光了!
-
然而,还有新的bug了。。。在UserController_Test.php里面初始化UserController之后,在调用一人成员函数的时候就会报错:Create object from empty object。。。于是我又去看框架的CController,Controller,定位到 public __construct($id,$module = null),应该是在Tests目录下初始化controller的时候没有像protected目录下那样自动生成一个controller流水号,于是我改写一个继承了CController的Controller的构造函数 public __construct() { parent::__construct(uniqid()); } 再去终端测试,然后成功了!
-
下面是一些截图:
这里贴一下测试覆盖率的报告图片(绿色为测试覆盖到的代码,红色的代表没有覆盖到):
- 解决了问题,好开心!虽然被它困扰了好几天了,谢谢作者Sebastian Bergmann,他的github主页是sebastianbergmann (Sebastian Bergmann) · GitHub 8:50上课,然而我还在宿舍码这份总结回答,我要去上软件工程课了。。。
总结简要解决步骤:
- 在Ubuntu下用sudo apt-get install phpunit安装好phpunit,接着安装selenium: sudo apt-get install phpunit-selenium;
- 下载上面github中的dbunit(sebastianbergmann/dbunit · GitHub)代码包(或者denglitong/dbunit · GitHub),将src/Extensions下面的Database目录拷贝到phpunit安装目录中的/usr/share/php/PHPUnit/Extensions下,记得修改/Database/Autoload.php增加一行: "phpunit_extensions_database_testcase_trait" => "/Extensions/Database/TestCaseTrait.php" ;
- 在yii框架中的protected/tests/unit中写单元测试controller类的时候记得要重写构造函数: public __construct() { parent::__construct(uniqid()); } ;
- 在项目代码的protected/tests目录下在终端执行phpunit unit/UserController_Test.php,即可正常执行单元测试 ;