就一般的开发程序员而言,code过程中调试、测试都是必不可少的。受影响于从事C++开发时养成的习惯,调试呢有断点调试,开发测试呢有单元测试。然饿,作为一种Web开发脚本语言,PHP断点调试[看不到变量及堆栈信息]:一堆的var_dump,echo??或者稍有点技术含量的log_message?更甚至借助第三方工具Xdebug?。。。。。这点我们暂不考虑,此处讨论的重点主要围绕“单元测试”。
无论是测试即有代码还是为编写新的代码,亦或是为重构老的代码做准备,单元测试的作用归根结底就是保护。正确的单元测试就是确保测试代码准确隔离(isolate)了测试代码,常见的有TDD,BDD,DDD(领域驱动开发)。
TDD,即测试驱动开发,是一种利用测试受益的方法论(或者说实践准则)。简单地说,TDD 就是在写代码前先写测试,并严格遵循red => green => refactor(错误 => 正确 => 重构)的流程,所以才叫做“测试驱动开发”。一般大致两种情形是适合的:1.准备编写自己觉得“没谱”的代码;2.准备重构即有代码,有可能是改善,也有可能是添加新的功能特性或处理新条件的逻辑,再有就是修复 Bug 等,在这里我都笼统的归为重构。
Bug 通常都是用户在使用过程中反馈来的(我把测试人员也算在用户之中),用户接触不到更深更内在的结构,他们都是通过用户界面来感受到软件系统的问题的。此时最好的入手点当然就是重现 Bug,而我们刚说过单元测试覆盖不了上至用户界面的层级,所以重现 Bug 都是从验收测试开始的,由此入手一层层抽丝剥茧,经历集成测试最终定位到单元测试。这一趟下来不但 Bug 解决了,而且连带着把一批复杂的系统交互都用测试覆盖了,这样用不了多久你就会发现该补的测试也都补的差不多了。
BDD(行为驱动开发,Behaviour Driven Development),比如用户使用过程中反馈的Bug,自上而下补 Bug 测试。
PHP常见的单元测试工具可参见:https://codegeekz.com/12-best-php-automated-test-frameworks/,此处我们简要介绍phpUnit的简单实用过程。
安装PHPUnit
访问phpUnit官网https://phpunit.de/下载相应版本的phpUnit,此处我们通过Composer方式安装:
php -r "readfile('https://getcomposer.org/installer');" | php
composer require --dev phpunit/phpunit ^5.7
编写PHPUnit测试
MVC框架下的controller中新建一个tests文件夹:
1. 针对类Class的测试写在类ClassTest中; 2. ClassTest(通常)继承自PHPUnit\Framework\TestCase;3. 测试都是命令为test*的公用方法,或者在方法的文档注释块中使用@test标注将其标记为测试方法;4. 在测试方法内,类似于assetEquals()这样的断言方法来对实际值与预期值的匹配做出断言。比如下图中phpUnit测试数组操作:
PHPUnit支持对测试方法间显式的依赖关系进行声明,这种依赖关系并不是定义在测试方法中的执行顺序中,而是允许生产者返回一个测试基准(fixture)的实例,并将此实例传递给依赖关系。
文档注释块中“用@depends标注来表达依赖关系”。比如我们对上图中的测试用例做出分离:
TIPS:默认情况下,生产者所产生的返回值将“原样”传递给相应的消费者,这意味着,如果生产者返回的是一个对象,那么传递给消费者的将是一个指向此对象的引用,如果需要传递对象的副本而非引用,则应当用@depends clone替代@depends。
当某个测试所依赖的测试失败时,PHPUnit会跳过这个测试,通过利用测试之间的依赖关系,缺陷定位得到了改进。
对于有多重依赖的测试【一对多】,其中第一个参数是第一个生产者提供的基境,第二个参数是第二个生产者提供的基境,以此类推。
数据供给器为测试方法提供参数,文档注释块“@dataProvider additionProvider”,数据供给器方法additionProvider必须声明为public,其返回值要么是一个数组,其每个元素也是数组;要么是一个实现了Iterator接口的对象,在对他进行迭代时每一步产生一个数组。每个数组都是测试数据集的一部分,将以他的内容作为参数来调用测试方法。
对异常进行测试:/*** @expectedException InvalidArgumentException*/
对错误进行测试:/*** @expectedException PHPUnit\Framework\Error*/
命令行测试执行器
PHPUnit 命令行测试执行器可通过 phpunit 命令调用,phpUnit命令不可用时,以PHP5.6版本为例:
wget https://phar.phpunit.de/phpunit-5.7.phar
chmod +x phpunit-5.7.phar
sudo mv phpunit-5.7.phar /usr/local/bin/phpunit-5.7
phpunit-5.7 --version
phpunit-5.7 --help
组织测试
PHPUnit 的目标之一是测试应当可组合:我们希望能将任意数量的测试以任意组合方式运行,例如,整个项目的所有测试,或者项目中的某个组件内的所有类的测试,又或者仅仅某单个类的测试。
PHPUnit 支持好几种不同的方式来组织测试以及将它们编排组合成测试套件。下面介绍了两种最常用的方法:
用文件系统来编排测试套件
最简单的大概就是把所有测试用例源文件放在一个测试目录中。当 PHPUnit 命令行测试执行器指向一个目录时,它会在目录下查找 *Test.php 文通过对测试目录进行递归遍历并运行测试。
phpunit --bootstrap src/autoload.php tests
用 XML 配置来编排测试套件
测试替身
转自:https://phpunit.de/manual/current/zh_cn/phpunit-book.pdf
https://www.ibm.com/developerworks/cn/opensource/os-cn-php-autotest/
http://www.thinkphp.cn/topic/37779.html
网友评论