单元测试 - 项目例子

  • 作者:KK

  • 发表日期:2016.3.18

  • 更新记录:2016.11.27

    把以前自己写不完整的demo换成了xoa项目


要点速读

  1. 实际项目中就是在test方法里写下针对项目的代码调用做各种不同的参数运行看看断言的结果

  2. 测试代码不应该关注类的加载,所以尽量别在new之前include代码,应该让被测试的项目自带autoload加载,测试框架bootstrap的过程中把被测试项目的autoload一起注册

  3. 本文章下面提供了一个叫xoa的开源项目提供给大家做参考


正文

上面你基本知道单元测试的知识和大概怎么编写了,接下来要应用到我们实际的生产中

假设我们有一个项目,项目里有个类叫A,希望修改它之后能方便快速地确认它能不出错,首先我们要准备一下这个A

为了模拟这些,我们先创建E:\project1目录并假设这里是某个软件产品的项目目录,接着创建E:\project1\A.php,里面编写如下代码:

class A{
	public function getXX(){
		return 1;
	}
}

然后在预启动脚本tests\unit\_bootstrap.php里写下

define('TEST_PROJECT_PATH', 'E:/project1');	//定义被测试的项目目录常量,未来可能经常用到
include(TEST_PROJECT_PATH . '/A.php');

接着我们在HelloWorld测试用例的testMe方法里编写:

$a = new A();	//在预启动脚本里加载了
$this->assertGreaterThan(0, $a->getXX(), 'getXX的值居然不大于0!');

运行后应该是有1次成功的断言

接着修改A类里面的代码变成return -1,再运行,当然就会提示失败了,这样的话,当A类未来变大了,有好多个方法了,有互相调用的情况,比如getXX方法和getYY方法都调用了私有的_getZZ方法,你一旦修改了_getZZ方法的话,以前可能要手动测试getXX方法和getYY方法是否都运行正常,但现在只要跑一趟单元测试,针对getXX方法和getYY方法的运行结果写下断言就好了


加载问题

既然要使用单元测试去测定一些类的方法是否运行正常,那要new这些类当然要加载进来,一个项目有好多类,如果照上面所说在预启动脚本里include的话,那要写多少行?另外,项目增加一个类,又要在这里补一句include?

才没人做那么笨的事啦,其实只要在预启动脚本里加载你要测试的项目的初始化文件,这个初始化过程中必须注册一个autoload函数,实现自动加载,然后使得单元测试代码里new的时候能自动加载到相应的类就可以,关于自动加载这块建议使用PHP的psr4标准,未来我会出相关文章讲psr4标准但现在没有,而另外会尽快给出简单的样本代码给大家下载参照


项目例子

有些有在疑惑学会这些后,在实际项目中到底应该如何落实这些测试代码,怎么写,对哪些进行测试

为了解决这些疑惑,我顺便也做了一个叫xoa的开源项目,测试代码在server/tests目录中

这是一个针对Yii2框架的应用项目做测试的例子,实际上当然还能针对其它任何框架或自定义开发的东西做测试了

要将这个项目的测试代码跑起来,务必先看看项目的文档里面的运行部署运行测试用例两个章节

简单的日常应用就是,当xoa的代码被开发人员修改后,通过test-tools.bat程序运行一下全部测试,server\tests\unit目录里面的单元测试代码就会按照预期调用相关的class,以不同的方式执行它们的各种方法传递不同的参数,断言一下执行的结果是否符合

如果全部断言通过,说明本次对xoa的修改安全度起码有85%以上,因为一般要测试的问题都已经写在单元测试里了;测试代码并不能将所有角度都全部测试,因为程序员可能会写漏一些角度的测试代码,比如数据搜索的测试,搜索条件组合花样百出,如果1000个商品分类里有其中3个有问题,那为了准确找出这些问题,程序员是不是要写1000种不同商品分类的测试代码?

这不现实,而且分类还在增加,所以测试代码确实无法完美地测试所有问题,但大部分问题已经写好测试代码后,一旦修改业务逻辑,你不再需要人工访问这里那里的页面测试刷新测试刷新……而只需要按一下bat的命令就可以自动跑一次,甚至设定系统定时程序跑命令