最近研究的了一下php的单元测试,使用的测试工具是phpunit,下面来分享一下我的经验。
-
首先要说为什么要用单元测试
很多人以为写代码写完没bug能运行就行了
其实不是,我们写代码是为了什么,肯定是为了能够重复运行。通过良好的API设计分割需求,那么在重构的时候API就基本不用变化,测试文件也不用重写。那么在以后重构的时候,只要unit test覆盖的够好,基本跑一遍就知道有没有改成傻逼。可以节省大量的时间。
-
代码覆盖
这里提到了一个词,代码覆盖。在单元测试的时候我们经常通过代码覆盖率来判断模块是否测试的完整。那么什么是代码覆盖率呢?覆盖率通常作为一个参考值来反应应用的质量。覆盖率反应测试脚本对应用的覆盖情况。以单元测试覆盖率为例,通过一定的工具比如emma(针对java应用),可以看到这些单测case对于应用的类覆盖,行覆盖,方法覆盖,块覆盖(可以理解为分支覆盖)情况。通过不断提升覆盖率的值,对于关键功能或者代码路径的覆盖,能够有效的保证应用迭代过程中,应用的质量。下面是一段针对php的单元测试代码覆盖率报告图片(绿色为测试覆盖到的代码,红色的代表没有覆盖到)。
-
安装
首先肯定是安装测试工具,这里我使用的是windows系统。先去官网上找到对应的phpunit版本下载,目前官网首页上有三个版本提供下载
这里一定要先确认本地的php项目的版本,比如我的环境是PHP5.5的,但是我第一次安装时装的是PHPunit5.7版本,结果导致按照教程测试的时候一直提示语法错误。
下载完成后可以按照官方手册的指导进行安装,这里放上PHPunit4.8版本的地址。
-
代码内容
整体逻辑来说,使用PHPunit一共分为两个文件夹,即功能文件夹和测试文件夹。
举例来说。首先是要测试的功能模块文件,如图所示是adt_coupon.php文件
然后是测试文件adt_couponTest.php
在这里可以看到,我定义的类NameTest在继承phpunit自带函数的时候,在前面加了一个反斜杠”\”,这是在4.8版本中的写法,和新版中的写法有所不同。同时,在我们的功能文件中所需要获取的传入的参数,如$_REQUST[‘member_name’]等,我们可以在测试文件中使用phpunit自带的setup方法,在其中定义。
在index.php里,主要放的是我们需要用到的一些引用文件路径
autoload.php是我们在执行自动化单元测试时的主要文件,在adt_couponTest中调用的一些方法,我们需要在这里进行生声明
这样最基本的单元测试内容就完成了。
-
使用
使用PHPunit测试,首先要通过命令行的形式进入到之前所说的主目录,如图
之后执行自动测试命令就可以了
phpunit –bootstrap mobile/control/autoload.php test/tests
这里可以看到命令分为四部分,第一部分是phpunit,第二部分是–bootstrap,这两部分是不变的,第三部分是mobile/control/autoload.php,这里是要指明autoload.php文件所在的路径,第四部分是测试文件所在的路径
-
常见问题
- 在执行测试后,如果返回的是如——Class Error: xsctx\agg\language.isn’t exists!,这种问题,说明没有把需要调用的函数加进到命名空间中去,这时我们要找到调用函数所在的文件,然后在头部把自己定义的命名空间加上。
- 在执行测试后,如果返回的是如——Fatal error: Class ‘Language’ not found in F:\BaiduYunDownload\111\server-php\core\framework\function\core.php on line 123 ,说明缺少引用文件。
- 在执行测试后,如果返回的是如——Fatal error: Call to undefined function C,也是缺少引用文件。
有兴趣的可以参考微软MVP写的一篇文章进行学习 30天快速上手TDD