最佳开发实践:自动化单元测试(PHP)

自动化单元测试

本文档主要是介绍一些已知的理论、工具和相关的实践。

成本 << 收益

一件事情,只有当我们认可是值得时,才更愿意为之付出努力。而从长远角度看,自动化单元测试的收益远大于成本。原因在于:

 

1、可引导编写更规范的代码,以及尽早发现隐藏的BUG,降低维护成本;

风格良好、规范的代码(可从注释、继承深度、圈复杂度、稳定性、TODO数量等方面衡量)应该是更容易维护的,因为阅读它的开发人员不需要过多的学习成本,也不会觉得修改很难或者怕引入新的BUG。

在 开发初期发现BUG并修复,成本是很低的,因为这只是消耗开发人员的时间。一旦代码上线后并出现BUG需要修复时,这时的成本是非常高甚至有时难以估算, 因为从项目流程上要经过报障、开发、测试、发布等需要跨部门沟通环节,从业务上可能也已造成了不可逆的副作用,如经济损失和数据污染。特别当直接经济损失 时再来考虑“一行代码值多少钱”这个问题会更显深刻,但这些问题不是不可以避免的,只需要我们再谨慎一点,测试再全面一点。如果依然觉得手工测试很痛苦,可以尝试将之自动化。

 

2、结合自动化测试,提高测试人员手工测试的效率;

当出现问题时,很多时候都不完全是个人的问题,而是团队的问题。所以作为开发人员,我们应该对前端、产品、PMO表示友好,同时包括测试人员。这里说的友好更多是指不过多占用他们不必要的时间反而能提高他们的效率、最终高效工作。

测试人员需要更关注不能用自动化测试验证的功能验收,如果测试人员不需要再为语法错误这种基本问题纠缠时,他们会为此感到开心的;如果不需要再为接口返回的数据担忧时,他们会更欣慰。

对自己负责,对自己的代码负责,就是对测试人员最友好的方式。

 

3、便于自动化集成,一次编写、持续收益。

当 然,测试的代码也是需要同步更新维护的,以便保持生气。但是,测试的代码明显也是可以不断重复利用的。通过自动化单元测试,我们可以时刻(假设自动执行的 间隔很短或者随时手工执行)验证我们现在、过去编写的代码都能通过严格的测试验证,而不是主观上认为“应该不会再有其他问题了”。同时可以检测当业务规则 发生变化时、在不同环境上以及其他人的做出修改时,我们的项目代码依良好然运行。我觉得这点很重要,毕竟人都有一定的健忘性,而计算机的自动化测试则很好 地保证了这一点。

最佳开发实践:自动化单元测试(PHP)

测试驱动开发

测试设计

在进行架构分析、设计时,预先考虑系统结构的可测试性也是大有裨益的。

意图导向编程

最佳开发实践:自动化单元测试(PHP)

在编写代码前,先写测试代码,更容易提高关注点。

因为,在开发过程中, 大多时候会被外界打断(如需求沟通、线上问题处理、临时会议等),而通过单元测试则可以让你“几乎忘却需要做什么”的情况下重新让你回到之前的状态,特别在并行开发多个不同项目的需求时尤其重要。

除此之外,遵循“红-绿-重构”这样的流程,我们可以在更高的层面关注需要实现的功能需求,并自顶而下地进行设计优化,精益代码。

这里面包含了以下两种思想:

1、做正确的事,比把事情做正确更为重要。

2、设计软件有两种方法:一种是简单到明显没有缺陷,另一种复杂到缺陷不那么明显。—— 托尼·霍尔


编写测试的原则、模式和指导

首先应该意识到,测试代码和生产代码一样重要。其次,测试代码也应该和生产代码一样被同步维护更新,这样才能保持生气,更大地发挥作用。只有当不断地对测试的代码进行修修补被,我们才能保持自动化测试这张“安全网”常新。

 

F.I.R.S.T.原则

快速 Fast

独立 Independent

可重复 Repeatable

自足验证 Self-validating

及时 Timely

构造-操作-检验(BUILD-OPERATE-CHECK)模式

这个模式也可以理解成:“当... 做...,应该...”。其中,构造包括测试环境的搭建、测试数据前期的准备;操作是指对被测试对象的调用, 以及被测试对象之间的通信和协助交互;最后检验则是对业务规则的断言、对功能需求的验证。

如何编写高效测试代码

1、与产品代码分开,与测试代码对齐

2、利用测试骨架(phpunit-skelgen或者自定义生成器)自动生成测试代码

3、使用测试替身、测试桩构建昂贵资源、制造异常情况

4、每个测试一个概念

 

自动化测试执行、集成与反馈

单元测试执行的方式

下面将执行一个单元测试函数,到执行一个单元测试系统,介绍说明各种执行测试的方式。

1、执行单个测试函数

phpunit --filter Your_Filter_Name ./Your_Test.php

2、执行指定单元测试内某一组测试

phpunit --group Your_Group_Name ./Your_Test.php

3、执行单个测试文件

phpunit ./Your_Test.php

4、执行某个目录下全部的测试文件

phpunit ./Your_Directory/

5、执行测试套件

测试套件是指定的一组单元测试,其中可以包括指定目录、指定文件,以及指定的顺序等。

如果需要执行不同位置上的多个文件、多个目录,以及需要一组指定的系列来执行,或者更多的规则限制,可以使用phpuint的XML配置文件来控制。执行的方式如下:

phpunit -c ./your_phpunit.xml

6、执行测试系统

通过简单地编写shell脚本,我们可以把多个已涵盖项目各方位测试的测试套件结合起来,构成一个测试体系,从而形成一个更大的“安全网”。执行的方式也就简单成:

./run_tests.sh

集成与反馈

Selenium的使用(可视化Web界面和交互测试)

与Jenkins、Sonar的集成(持续构建、测试报告)

与Phing的集成(部署测试)

crontab和邮件报警(内部快速检测)

 

实践案例

出于对业务的保密,这部分内容有删减。。。

与Jenkis、Sonar的集成

最佳开发实践:自动化单元测试(PHP)

最后说明

此文档标题虽然为自动化单元测试(PHP),但是:此文档不仅仅是关于单元测试,更多是关于自动化测试;此文档的实践案例基于PHP,但这里所说的思想、原则等也同样适用于其他语言。


转载于:https://my.oschina.net/dogstar/blog/370605