在目前比较流行的敏捷开发模式(如极限编程、Scrum方法等)中,推崇“测试驱动开发(Test Driven Development,TDD)”——测试在先、编码在后的开发实践。TDD有别于以往的“先编码、后测试”的开发过程,而是在编程以前,先写测试脚本或设计测试用例。TDD在敏捷开发模式中被称之为“测试优先的编程(test-first programming)”,而在IBM Rational统一过程(Rational Unified Process,RUP)中被称为“测试优先的设计(test-first design)”。全部这些,都在强调“测试先行”,使得开发人员对所作的设计或所写的代码有足够的信心,同时也有勇气进行设计或代码的快速重构,有利于快速迭代、持续交付。重构的前提就是测试就绪(testing is ready),在这样的前提下,重构的风险就很低,不然就有比较高的风险。编程
TDD具体实施过程,能够看做两个层次,如图1所示:工具
在代码层次,在编码以前写测试脚本,能够称为单元测试驱动开发(Unit Test Driven Development,UTDD)单元测试
在业务层次,在需求分析时就肯定需求(如用户故事)的验收标准,即验收测试驱动开发(Acceptance Test Driven Development,ATDD)。测试
图1 TDD的两个不一样层次ui
先来讨论UTDD,如图2 所示。在打算添加某项新功能时,先不要急着写程序代码,而是将程序可能会碰到的特定条件、边界值、上下文等想清楚,为待编写(类或方法)的代码先写好测试脚本。而后,利用集成开发环境或相应的测试工具来执行这段测试用例,结果天然是经过不了(失败)。利用没有经过测试的错误信息反馈,了解到代码没有经过测试用例的缘由,有针对性的逐步地添加代码。为了要使该测试用例经过,就要补充、修改代码,直到代码符合测试用例的要求,得到经过。测试用例所有执行成功,说明新添加的功能经过了单元测试,能够进入下一个环节。这样的流程也适合代码修改或重构,真正执行时,也不会严格按照这样的流程去作,但最基本要求是:先写好测试脚本(代码),再写产品代码并经过测试。按照UTDD作法,不是先写产品代码的类,再写测试类,而是先写测试类,再写产品的类。编码
图2 UTDD执行的过程spa
UTDD从根本上改变了开发人员的编程态度,开发人员不能在像过去那样随意写代码,要求写的每行代码都是有效的代码,写完全部的代码就意味着真正完成了编码任务。而在此以前,代码写完了,实际上只完成了一半工做,远没有结束,由于单元测试还没执行,可能会发现许多错误,一旦缺陷比较多,缺陷就比较难以定位与修正。UTDD在于促进开发人员思考功能特性的应用场景、异常状况或边界条件,写出更完善的代码,避免犯较多的错误。其次,也确保测试具备独立性,不受实现思惟的影响,确保测试的客观、全面。这一点,对开发人员测试本身的代码是必要的。若是是倒过来,先写产品代码(即功能实如今前)再进行测试,那么测试会受实现思惟影响。例如,咱们本身写的文章本身检查,有时很明显的问题都发现不了,就是受实现思惟的影响。通常来讲(多数状况下),开发人员测试本身的代码有两个障碍:思惟障碍和心理障碍。心理障碍是指开发人员对本身的代码不会穷追猛打,发现了一些缺陷,极可能会适可而止。咱们知道,实际上缺陷越多的地方越有风险,越要进行足够的测试。最后,UTDD也确保全部代码的可测试性,每一行代码获得了测试,比较完全地确保代码的(微观)质量。设计
许多研发人员不习惯UTDD这种模式,推行UTDD会遇到比较大的困难,那TDD的实施能够移到业务层,推行ATDD,即在设计、写代码以前,明确系统功能特性的验收标准,这比较容易推广实施。例如,在敏捷开发模式中,每一个用户故事的描述过于简单,是不具备可测试性的。例如,开发一个在线旅游网,能够提供交通、酒店、门票等预约服务,有一个最基本的用户故事:3d
像这样的用户故事,若是不加验收标准,开发实现起来很容易,在数据库某个表中删除一条记录,在其它关联表上修改相应的标志位便可。但实际的业务不会那么简单,说取消就取消?不须要有一个时间提早量?取消必定成功吗?收不收相关的费用?是否须要线下处理的时间?是否须要通知用户?经过什么方式通知取消成功或失败?要回答这些问题,就是要给这个用户故事增长“验收标准”,如:
取消前,须要提醒用户再次确认
需提早24个小时取消
须要4个小时处理时间,才能知道取消成功与否
这类取消须要收取总金额10%的费用
无论取消成功与否,采用邮件和短信双重通知
用户过后能够查询取消的相关记录
须要保留客户和旅行网双向操做记录日志
这样,这个用户故事才具备可测试性,开发人员也会清楚如何实现这个用户故事,实现的结果和产品经理所指望的结果就不会有太大差别。
从ATDD演化出来一种具体落地的开发模式就是BDD(Behavior Driven Development,行为驱动开发)。BDD只是将验收标准更加明确化,能够看做是ATDD的实例化,即列出用户故事所可能遇到的应用场景,并且将这种应用场景的表达方式规定为GWT格式,即:
BDD再往前推动一步,就是需求实例化(Requirements By Example,RBE),更加明确需求的具体表现。仍是以上面用户故事为例,能够创建相似下列内容的需求实例化。
需求越明确,用户、产品经理、开发与测试等之间的理解就越一致(on the same page),更不产生误差和误解,有利于开发和测试的工做。基于RBE,开发人员写产品的代码,测试人员能够独立写测试的代码,产品经理的工做也会变得轻松,不须要太多的解释、不须要回答开发和测试的各类问题。
从需求角度看,BDD和需求实例化比较完全地明确需求,统一用户、产品经理、开发与测试等认识,让你们处在一个层面上,使研发工做更高效。
从测试角度看,需求即测试,产品的需求就是测试的需求,需求能够被执行,即一步到位,将需求变为自动化测试脚本,开发出来的功能特性随时能够被自动验证。
TDD一改以往的破坏性测试的思惟方式,测试在先、编码在后,更符合“缺陷预防”的思想。这样一来,编码的思惟方式发生了很大的变化,编写出高质量的代码去经过这些测试,在进行每项设计、写每一行代码时都要想一想用户的真实需求、应用场景和一些例外等,确保实现的功能特性符合预期,并具备健壮性。测试,也从之前的破坏性的方法转移到一种建设性的方法中来。在这种积极心态的影响下,开发人员的工做效率和产品的质量都会有显著的提升,真正实现“质量是内建的(Quality is built in)”的目标。