测试驱动开发起源于XP法中提倡的测试优先实践。测试优先实践重视单元测试,强调程序员除了编写代码,还应该编写单元测试代码。在开发的顺序上,它改变了以往先编写代码,再编写测试的过程,而采用先编写测试,再编写代码来满足测试的方法。这种方法在实际中能够起到非常好的效果,使得测试工作不仅仅是单纯的测试,而成为设计的一部分。为什么这么说呢?
在编写程序之前,每个人都会先进行设计的工作。可能有些人的设计比较正式,绘制模型,编写文档。有些人的设计只是存在于脑海之中。且不论是设计是精细还是粗糙,你都为随后的编码活动制定了一个标准。这个标准的明确程度和你的设计的细致程度有关。但应该承认,这个标准是不够细化的。因为你的设计不可能精细到代码级的程度。而标准不够明确的则会产生一些问题,例如,在编写代码的过程中,你还可能会发现原先的设计出现问题,从而中途改变代码的编写思路。这将会导致成果难以检验,进度难以度量。
既然以设计为导向的标准不够明确,不够具体。那什么样的标准才是合适的呢?只能是代码。因为代码是最明确、最具体的。所以测试优先的本质其实是目标管理。编写测试代码其实是在制定一个小目标。这个小目标非常的明确,它规定了你需要设计的类、方法。以及方法需要满足的结果。这些目标制定完成之后,你才开始编写代码来达成该目标。测试的目标要比设计的目标粒度更小,但是成本上却更为经济。其原因有四:
细粒度的设计需要花费大量的成本,虽然CASE工具都提供了代码自动生成的功能,但结果往往难以令人满意。所以,设计如果要做到和测试相同的粒度,成本不菲,如果粒度不够细,指导的意义又不够。
减轻了测试的工作量。无论是否进行设计工作,测试工作都是不可避免的,先进行单元测试,可以减少后续的测试工作量。
采用测试优先的过程中,设计的粒度较大。因为测试可以实现一部分的设计工作。这样,设计上可以节省一些工作量。例如,你不再需要将类图细化到每个方法。
在编写测试代码上花费的成本,会在回归测试上得到回报。自动化测试的最大好处就是避免代码出现回归。两相权衡,编写测试的代价其实不高。
你也许会说,我既不进行如此精细的设计,也不事先编写测试代码,这样的成本不是最低吗?请注意,我们的前提是在讨论高质量的软件设计。在一些规模较小或是开发人员能力极强的项目中,确实可以如此办理。但是对于强调质量的大项目,这种处于混沌状态的开发思路是不可取的。
测试优先是软件开发中一种细粒度的目标管理方法,通过明确的目标,推动软件开发的进行。
在业界中,采用测试作为评价软件标准的做法是非常常见的。例如,sun公司就专门设计了测试软件,对各个实现J2EE规范的产品进行测试。使用测试作为规范的最大好处就是明确、具体。
使用测试代码建立目标,编写代码完成测试目标,再制定下一个目标,如此循环,构成了测试驱动开发的工作流程。在接下去的篇幅中,我们开始讨论测试驱动开发中需要注意的一些问题。
测试必须是自动化的
和自动化测试相对的是手动测试。手动测试有着自动化测试所没有的优势。最明显的就是简单。任何一位开发人员都能够进行手动测试。即便是用户,也很容易掌握手动测试,他们输入数据,并观察软件的反应(输出),从而判断行为是否正确。大部分的手动测试都是对输入和输出的检验,是一个端到端过程,很能说明问题。