虚拟座谈会:代码测试比率、测试驱动开发及行为驱动开发-1

上一篇 / 下一篇  2012-09-27 16:43:51 / 个人分类:杂谈

51Testing软件测试网MUBZuf8d

  过去几个月间,互联网上关于测试先行还是测试居后、代码测试比率或者行为驱动开发(BDD)是否真的是测试驱动开 发(TDD)的讨论进行得如火如荼。InfoQ就此访问了行为驱动开发(BDD)和测试驱动开发领域知名的专家们,请他们对测试驱动开发(TDD),行为 驱动开发(BDD)以及测试比率的运用发表各自的观点。(译注:此后测试驱动开发和行为驱动开发均用简称TDD和BDD代替。)

IY@(xv/A051Testing软件测试网4Nss6y,? c"s K

  座谈会成员:

Zh*O-c,WX.Z051Testing软件测试网6Q"y nN"W:CM)fI

  ● J. B. Rainsberg ——顾问及测试驱动专家,关注他的博客:The Code Whisperer

S(?/u&r/R6p%mh0

(b/ZYeB4]0  ● Dan North ——DRW Trading Group的精益技术专员, 行为驱动开发(BDD)的定义者51Testing软件测试网Fq3hg8YC8z'L0F!W

51Testing软件测试网 ] P2z^ t _)_,c.F

  ● Gojko Adzic —— 顾问,《Specification by Example》及《Bridging the Communication Gap》作者

O ciH$oU4DP@i0

"`x*EK&b0  ● Ron Jeffries ——极限编程(XP)及敏捷模式的独立顾问,曾指导过极限编程(XP)的项目

)?cM+OD051Testing软件测试网D!E oVh| DC_ a

  ● Steve Freeman —— 敏捷讲师及顾问,《Growing Object Oriented Software, Guided by Tests》作者

8].|3GM1K'Q @3C0

9jIS3A6tf.JKzn0  问题:对项目而言,你认为哪些标准会影响你做决定,是采用TDD还是BDD或是什么都不用呢?

1D+mp)J+e\A"A051Testing软件测试网a)BRCg

  JB:对这个话题做概述,我觉得有点不合适,莫不如让我来说明下,我在什么时候会用到TDD和BDD,以及这么做的理由吧。

waVO$pI;Np!i0

;^l9G?MEelV0  我第一次接触TDD是因为我试图寻找一种方法来减少代码中的错误(也叫代码缺陷或Bug)。 曾经,我在程序中引入的错误数量让我一度认为自己永远都无法完成编码——不管我怎么努力,都看不到任何希望。我猜测,如果那个时候,能自己测一下代码,就 能找到许多简单、愚蠢的代码并自己修复掉。TDD对我来说,并不只是为了不让别人觉得你写的代码有多糟糕,而是避免你错误地认为自己已经完成了编码,却留 下一大堆Bug。然而,TDD帮我解决了这个问题,多年之后,我还意识到TDD不仅帮我避免了程序逻辑的错误,更帮我减少了程序设计中的问题。在我运用 BDD之后,我发现BDD帮我减少了许多在选择特征与完成特征时的错误。日复一日,我逐渐明白代码的错误不仅让我费时费力,也让我无法按时完成编码工作。这个时候,我开始在项目中贯彻实施TDD与BDD的方法。51Testing软件测试网6P|%_ ~?gLNq

51Testing软件测试网4u cZ%A.z6nL

   让我们再回到问题本身,我鼓励大家去思考为什么你们需要做TDD,想想你的理由。不要限于典型的实施TDD与BDD的理由,例如:更好的设计、更少的程 序缺陷、更有商业价值的产品特征以及更少的无用功。我鼓励人们多思考一下驱动你这样做的原因,这才是重中之重。我相信你会发现,一旦你采用了这两种方法, 必然能按时完成分配的任务,因为这会让你更有条不紊,而不是到后来手忙脚乱。当然,我认为这些理由是因人而异的。51Testing软件测试网?)yao wMk&f0F

u;|%y-n(Xf5k`0  Dan:首 先允许我给出一些定义。TDD是一种编程技术,它引导程序员思考自己的代码是如何被其他代码所使用,从而避免由代码实现引起的“意外设计” (emergent design)。你首先要写一个测试来描述如何使用下一块代码,然后实现这块代码,并保证它通过测试。这项技术是需要编程技巧的,并且需要考虑何时进行合 适的运用(我稍后会展开)。这样做有很多优点,编写测试帮助你理解行业知识并帮助你更好地去命名。一个测试可以发现理解上的差异(“你认为在这个用例中应 该怎么做?”),当然,一整套自动测试可以帮助我们发现回归测试中的缺陷。

d_1~&^1I"hT.TZ)M0

e'o1[A7c0  我并不认为我们必须决定是否在这个项目中采用TDD,你几乎 可以在任何一个项目中使用TDD。然而,我建议程序员在采用TDD前思考一下,这样做是否有价值。不可否认的是,除了TDD,我们还有其他很多方法可以用 来做设计、对某个行业探索和建模以及减少回归测试的风险。有些项目,最有效的方法是逐一采用这些方法,而有些项目不是。不夸张地说,我认为TDD是每个程 序员都应该了解,并知道如何去做的、很有用的方法。对于重构,我也持有相同的意见——你必须去了解这个方法,但你需要时间的磨练,去区分何时何地采用这种 方法,或转投他法。51Testing软件测试网#_d:@)R K`5y2V

G6~vQ K/i1R+s0  BDD是一种开发方法,形式类似于极限编程(XP),但不能把它单单看成是TDD的一种实现方式。BDD的作用是把 利益关系人、交付团队等不同方面的项目相关人员集中到一起,形成共同的理解,共同的价值观以及共同的期望值。如果你没有碰到过这样的难题,那就可能是哪里 出问题了。当然,我也是最近才渐渐地运用起这种方法,之前我都是与较小的团队一起工作,通常也能有比较迅速和通畅的利益关系人反馈。因此,由理解不同而造 成影响的情况比较少见。通常,利益关系人会说:“这里你能帮我改一下吗?”或者“这不是我想要的,我来举个例给你。”

~%FWu0@w a/e'Y x,Io0

~#_\(i*yf0  BDD会从业务目 标着手,将这些目标与产品特征和故事衔接起来。BDD提供了如何确定你的验收标准的建议,以及你如何将这些标准落实到决定代码行为的自动测试上。如果你的 项目决定采用BDD方法,那就必须从整个项目的层面上来考虑问题(尽管你可以在子项目中运用BDD),而且必须拉上整个团队一起做。51Testing软件测试网"t2Ke6xl:?I

c\_-mA)po0  我赞成以下说法:只要能够提交合格的代码,那么每个程序员或配对编程的人员就都有权利以他们所偏好的方式交付软件。如果他们打算使用TDD,我们就应该支持他们这样做。如果他们打算做些其他的,只要团队成员没有问题,我们也可以允许。51Testing软件测试网Y(Dg'k|[X

51Testing软件测试网*j$X_M4P

  Gojko:这取决于你如何定义TDD和 BDD。看起来,在过去几年间,TDD的定义被局限在仅仅作为设计的单元测试。而BDD则变成以实例和业务导向的测试来驱动功能的、涵盖所有开发阶段的方 法。根据Brian Marick在《Agile Testing by Lisa Crispin and Janet Gregory》中的敏捷测试象限的定义,TDD应该在第一象限,而BDD在第二象限。我并不完全同意这点,但既然你的问题是什么是影响你采用TDD还是 BDD的标准,我假设你对TDD的定义是排除在BDD与其他方法之外的。基于这点,我们分析以下三个方面:

4_l%X6`J0

#V3LK1aL8q$e3t#{0  ● 这是个一次性项目吗?是否为了将技术的不确定性降到最低,从技术层面,帮助团队了解他们最终想要什么?在这种情况下,维护很多自动测试用例集合都是一种浪 费,而且极有可能团队真正需要的只是一小部分相关联的简单用户用例。因为我们不清楚技术壁垒,所以编写技术测试可能会是个问题。我可能会选择写一些指导性 的测试,而非教条式地为每个设计写一段单元测试。这符合Steve Freeman和Nat Pryce所著的有关《成长性面向对象软件》的大型系统测试

w-P2s~PbA0

+~,|-pocr%JX0  ● 项目的复杂度是否由技术所决定?我们是否认同我们所要完成的是技术上的,而非业务逻辑上的风险和不确定性?是否所有项目相关人员都是技术出身,能够读懂代 码?例如:搭建Web框架的项目、数据库平台的项目、查询系统的项目、或是云部署平台的项目。众多开源项目都可以归为这几类。如果是这样,那么偏技术的 TDD就比较适用了——我会用单元测试工具来驱动业务场景和技术设计。我可能还会在白板上写些例子以求得到普遍认同(BDD的核心概念),但我不会浪费时 间把这些例子录入到可执行用例或非技术自动工具(Cucumber)中了。51Testing软件测试网$Y'X [)X@h?

Lb m0J5Nz8z*j1q%b8d0  ● 项目是否也有复杂的业务逻辑需要讨论,或者存在不清晰的业务需求,需要在不懂编程语言的成员之间沟通的情况?如果是,我将各个击破。先使用实例来探讨业务 需求,确保大家对业务有共同认识。然后为这些实例建立规格说明书,并将这些实例录入到诸如Cucumber、FitNesse或类似的自动工具中去。最 后,用单元级别的测试来驱动代码的设计。51Testing软件测试网+i2Mo3JB&Jo

}.jzI+yw ]9w q0  Ron:我多希望在过去的半个世纪的开发生涯 中,我能够在每个项目中都运用这两种方法。我并没有发明这两种方法,我只是最早接触的那几个人之一。TDD和BDD让我确信,没有更好的方法了,这两种方 法也让我的代码缺陷数量大大降低。并且,当我更好地了解到系统或产品该设计成什么样子时,我的设计就更得心应手了。

yu0t-J'p5c0

.r p/I(@~,?0  TDD和BDD太难被超越了。

yJ2U5GQN h:c051Testing软件测试网%BP_!N PT9nG B

  Steve:你需要为你的系统写测试吗?如果需要,为何不在代码实现前就写完呢?这样一来,你就能知道怎么把测试变得更简单。你也并不可能把所有的测试用例一下子都写完,何不边写代码边完成测试用例呢?

l6H3so5o@$k2f051Testing软件测试网S!g]}-D J

  问题:现在似乎有种普遍的认识,认为TDD等同于单元测试,而BDD则等同于验收测试(无论使用的是哪种工具)。你们认为这种说法是否正确?其他类型的测试例如构件测试与系统集成测试 又是如何与TDD/BDD关联的呢?51Testing软件测试网Kv(y3R Ic(V

51Testing软件测试网h#ok`W:gL

  JB:我想从两个方面谈这个问题:TDD对我 的设计提供了反馈,而BDD则是对我们开发的产品理解提供了反馈。起初,我以TDD作为一种测试技术开始实施,慢慢地我把TDD作为设计手段,再后来把 TDD作为一种深入了解产品设计原理的方式。而对于BDD,我则一开始把它作为提醒我从真正终端客户和利益受益者的角度看待产品的一种方法,最终变成改进 业务与技术人员之间沟通的一种技巧。你可以看到,虽然测试在其中扮演着配角,却举足轻重。51Testing软件测试网~%I2j,|%i6r6_^-Fe

51Testing软件测试网'^H?J0K-`O2A

  我并不把TDD和BDD当作测试技术,我认为测试策略与TDD/BDD是无关的。无论项目使用TDD,还是BDD,还是什么都不用,我都期望从微测试(microtesting)、系统测试和可用性测试的角度来考虑这个问题。51Testing软件测试网.j*|:H9L%y

8XJb4|"o R0  Dan:这真的是不幸的历史产物。事实 上,TDD和BDD都涵盖这两种测试,甚至更多。Kent Beck在极限编程(此后在他的TDD书中)中说到——TDD在不同等级粒度中均能适用,这也契合Nat Pryce和Steve Freeman在《成长性面向对象软件》所描述的。你撰写用户级别的功能测试与低级别的单元测试的目的是相同的,都是为了阐述你希望代码如何表现。TDD 的激励作用多过于实际意义:如果你只为了得到更多的自动测试覆盖率而撰写自动测试用例,那不是TDD。类似地,你可以测试诸如并发、延迟、 failover或吞吐量等非功能性需求。

"B!w%Zu\fVUz0

c!_C O7\ h0  BDD之中用户级别测试与代码级别测试的区别更加明显。用户级别的测试是基于自我澄清和自动化的场景。并且这些构建的步骤可以在其他场景中重 用。代码级别的测试也叫做实例(或者规格Spec,虽然我不倾向于这么叫),与TDD相比更接近人的思考方式。时过境迁,有不少不同类别的工具出现。比较 有名的有:用户级别的跨语言工具Cucumber,以及代码级别的工具RSpec、NSpec等。我的经验是,我倾向于使用团队喜欢的工具。比如,大部分 的BDD源码,我用过时的JUnit与JMock的Hamcrest matcher library编写。最近,我用Python的py.test和nodeunit来写node.js,这与JUnit风格类似,“BDD风格”的框架在两 者中均有体现。因此我的建议是,这只是代码,如何实现它由你决定。

7U3Qj$O[(e;t0

*^l'c{3u TF0  Gojko:同样,这取决于你对 TDD,BDD以及其他概念的定义。我对Kent Beck著作的理解是用户测试与单元测试属于TDD范畴。而我对Nat Pryce和Steve Freeman的《成长性面向对象软件》中的理解是TDD包括系统测试,构件测试以及单元测试。我对规格说明书的解释是好的文档会将业务概念拆分,并自动 化,以求风险得到控制——如果大部分的风险来自于一个实例,我们则需要验证实例的Java方法;如果风险来自系统,我们则需要对系统进行30次的Web服 务运行和100次数据库运行。

f(iS ]Lu*[,k)|051Testing软件测试网Y7l+s$Q'~

  Ron:BDD起源于TDD的另一种描述。而现在,在Chris Matts和Liz Keogh手中,BDD演化成实现产品特征描述与验收测试的方法,这也是我所理解的BDD描述。51Testing软件测试网$P#n2fG;Ap#I*s5J%o

51Testing软件测试网l"G~;K6w*Bv4e

  而其他形式的测试,当然也很重要。我特别指出,我们需要把用户体验测试加入到你的测试列表中。关于构件测试和系统集成测试,敏捷项目的最佳方式 是使用持续集成(Continuous Integration)。这样,所有分散的构件就能关联起来,集成的系统所能承受的测试也随之增加。通常,这些分类很模糊。我们针对不同事件,在不同的 间隔运行不同的测试集,比如:新的类库或构件,或新构建的版本。这样的测试集包含了用以描述单元测试、验收测试等所有的测试用例。 测试的精髓在于,分清什么需要测试,尽量在创建或有变化的时候就进行测试。这就是我们防止代码缺陷和及时发现代码缺陷的秘诀。

8s2n'}/VW#] zu0

f0ib0  Steve:我可不会做这样的类比,很明显,这是基于对TDD的错误理解。TDD中最基本的问题是“我怎么知道这样是可行的?”——所有的业务和组织都可以这样去考虑问题。51Testing软件测试网g.wl'U4b

51Testing软件测试网U8o_!H kWO

  我并不认为将测试细分成筒仓(silo)会有多大帮助,相反顺畅的测试给团队带来自信,相信系统能够正常运行。

4l1Z!_'HiDz0

TAG:

 

评分:0

我来说两句

Open Toolbar