说起单元测试,多数同学应该都知道或听过,可能不少同学认为自己也写过,甚至觉得单元测试很简单有什么好培训的?其实这个事情还真没想象的那么简单!我基本可以比较负责任的说,你若没深入对单元测试做过研究,不知道Mock对象为何物的话,那么可能你以前写过的单元测试压根就不是单元测试。
单元测试是什么?
这个问题其实并不太容易一两句话说得特别清楚。先借用下百度百科的定义:
单元测试是在软件开发过程中要进行的最低级别的测试活动,在单元测试活动中,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
从以上这句定义我们可以看到,两个提取到到两个非常关键的字:最小粒度、隔离
● 单元测试是测试的最小单位,必须可信任的,可重复执行的。
● 如果测试的范围轻易的就会扩展到其他类或同类的其他方法,那就不再是最小单位,也就不是单元测试了!
例如:
类A中的方法CallMethod中调用了类B中的方法DoMethod,如果在编写测试的时候不把B类中的DoMethod隔离出来,造成单元测试CallMethod方法时,实际实行了DoMethod方法,那么这个测试方法不能算作是单元测试。(如何隔离会在后文详解)
单元测试的目的是什么?
有人曾给我一段非常简单的代码片段:一个方法,里面只是调用若干个其他方法,甚至也都没有任何返回值,然后问我这种代码写单元测试有任何价值?!完全是浪费体力!!
public class ClassA { public void CallMethod() { DoSomethingForYou(); DoSomethingForThem(); DoSomethingForMe(); } } |
其实提出这个疑问主要有两个原因导致:未能理解单元测试的目的是什么以及这段代码的可测试性并不高。(可测试性以及如何提高将在后面章节介绍)
单元测试的目的是用来确保程式的逻辑如你预期的方式执行,而并不是用来验证是否符合客户的需求的!通过单元测试来建立一道坚实的保障,防止代码在日后的修改中不会被破坏掉。
是不是很失望?单元测试并不是用来验证代码是否符合需求的。
事实上,单元测试是白盒测试的一种,而且需要开发人员来完成,最好是谁开发的代码就该谁来编写单元测试代码,因为代码的编写者最熟悉该段代码的目的,进而编写出验证该目的是否达到的单元测试代码。
单元测试并不能用来代替其他测试手段,不过是实践过程中确实会很有效的帮助开发人员自查代码,进而发现一些潜在的BUG。但这只是一个额外的收获,若不是采用TDD那样的测试先行开发方式,那么单元测试的根本目的不是用于也无法检验当前代码是否存在BUG的!
上面有说到单元测试最好是由开发人员自己来编写,用于验证该段代码是否符合开发者开发的预期要求。这里可能会有个疑问,既然开发者自己已经很清楚自己想要 结果是什么,直接运行一遍代码实际跑一次,通过断点调试不是就可以很方便的验证了嘛?再通过编写代码的形式,甚至比开发这个功能本身更多的代码,去验证这 个方法是否符合编写的目的,不是很傻很笨很累的办法么?
也许通过一个大家经常会碰到的实际场景能更好的说明:
一个项目开始,项目经理把需求拆解为若干个模块分发给不同的开发人员去完成。这样每个人可能只熟悉自己的那部分代码。当项目某个阶段开发完成并上线后,可能部分开发人员会离开项目进入别的新项目,留下个别人员继续维护;或者项目下阶段开发新进一大批人员并不熟悉当前项目;当然最常见的是,在修改BUG阶段是无法完全做到谁产生的BUG就安排谁去修改。