BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

TDD/BDD会导致不完整的单元测试吗?

| 作者 Mike Bria 关注 0 他的粉丝 ,译者 韩锴 关注 0 他的粉丝 发布于 2008年2月25日. 估计阅读时间: 4 分钟 | GMTC大前端的下一站,PWA、Web框架、Node等最新最热的大前端话题邀你一起共同探讨。

Peter Ritchie最近开始担心他认为很不妙的趋势,即开发者为了坚持TDDBDD 而无法写好单元测试。特别地,他认为对“交互测试”的顶礼膜拜,最终带来的后果是不完整的单元测试;测试无法证明某个单元(对象)能在它有可能工作的任何环境下正常工作。首先,Peter的想法中,最有趣的部分可能就是TDD与BDD之间不同核心目的的冲突。

Peter利用“类是真实世界概念的自然抽象”这一理念作为自己观点的基础。他认为良好的单元测试 应该能够验证这些自然抽象出来的类,但可能在未来的某个时刻开始,TDD和BDD将导致人们不去遵守这一原则:

我发现测试驱动开发(TDD)和行为驱动开发(BDD)这两种方法结合在一起后存在一个问题,那就是实践者只把系统各部分间的交互放在了最核心的位置,其实并没有做任何“单元测试”。他们只为了追随TDD和BDD的魔咒,最后却只见树木、不见森林,而成为盲目测试。单元测试的目标是独立的单元、应用程序中最小的可测试的部分。

Peter引用了Wikipedia's BDD entry中的一个例子来证明他的观点:

详细的测试仅测了4,294,967,296种可能性中的13种。这些测试可能很好地测试了一个系统预期的行为,但是并没有真正把EratosthenesPrimesCalculator当作一个单元来测试。如果系统只允许这样的行为,那么这些测试可以证明系统是正常的。但是,如果EratosthenesPrimesCalculator超出了这13种行为而被使用的话(这也正是将代码封装成类的目的:重用),那么它就算不是上已测试好的啦。

这个例子在很大程度上依赖于这样一个观点——一个单元的有效性/正确性完全是基于其名字所暗示的在现实世界中它所固有的特性。很多TDD的实践者会向这一点发起挑战,他们认为:一个单元的有效性只能在使用它的环境(系统)上下文中才能定义。JMock的作者之一Steve Freeman说道:

测试先行的交互测试的思想是理清一个对象与它的环境之间的关系。例如,你正在模拟一个DAO,但是DAO不是应用领域中一部分,它是实现领域的一部分。

而另一方面,很多做TDD培训的人会不认同这一点,他们认为:先行编写单元测试的主要作用在于它是一个单元模块该做什么、不该做什么的显式规约。下面文字源自于Mario Gleichmann的“TDD与按契约设计的对比”:

单元测试作为测试驱动开发(TDD)的一个重要组成部分,其作用并不在于能在多大程度上验证实现的正确性,而是有助于澄清单元模块行为的规约。事实上,驱动开发的东西应该是规约,而不是验证。你可以在行为驱动开发(BDD)的崛起中看到这种思想的回归。BDD其实就是要寻找一个充分的词汇表并用一种很自然的方式编写规约(当然,这也是可以被自动化测试的),以便将注意力重新放到“组件在特定条件下应具有哪种行为”这个问题上来。

从“单元模块是由其上下文定义的”这种观点中引申出来的一个推论经常被引用,这个推论就是:按照单元测试的定义,它并不能反映出整体系统的质量和有效性,相反,要想做到这一点,就要在开发阶段中增加各种级别的验收测试JS Greenwood写道:

虽然集成测试少得可怜,但所有事情都被独立测试过了——每一个组成部分都很干净、独立、被良好测试并且可以信任其正确性,(这也是单元测试的极限了)。但是如何保证所有组件都能协同工作呢?这是一个灰色(甚至黑色)区域,除非能充分地结合单元测试和集成测试。
查看英文原文TDD/BDD Leading To Incomplete Unit Tests?

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

需要么?不需要么? by han isaac

可是我们从来都不需要完整的测试啊。TDD是设计方法,不是测试方法。

Re: 需要么?不需要么? by Jacky Li

TDD是设计方法,不是测试方法。

是啊

TDD 既是设计方法,也是测试方法 by Zhang Charlie

TDD是设计方法,不是测试方法。


你看 Kent Beck 的 TDD 原著,有一半是讲如何用(单元)测试驱动设计,有一半讲是如何写好自动测试,而从 TDD 的标准定义中,也可以发现 TDD 至少是二合一的,尽管大师们可能更强调前半部分。

你还可以反过来想。xUnit 是什么工具?难道是设计工具?它首先是测试工具吧。

所以,客观和正确的说法是:TDD 不仅仅是测试方法,也不仅仅是设计方法。

“TDD 不是测试方法”的说法是片面错误的,或者说有逻辑缺陷。这种道听途说而来的误解,在网络上被以讹传讹,好像已经流传很久了。

比较可靠的敏捷教练和顾问 张恂
www.zhangxun.com

Re: TDD 既是设计方法,也是测试方法 by 陈 雷

charlie zhang说的非常对,就是基于测试的设计,那前提也是测试。所以离开测试而说TDD是不正确的。

Re: TDD 既是设计方法,也是测试方法 by Jacky Li

来来来,靠谱的人先给个TDD的标准定义

Re: TDD 既是设计方法,也是测试方法 by han isaac

不争了,我对TDD的理解不仅仅来自于大师的定义,也来与我自己的经历。我说的是我的体会:TDD是设计方法,如果我把TDD当作测试方法,我的测试很快就不能“驱动开发”了。

Re: TDD 既是设计方法,也是测试方法 by Tong James

Test-driven development,我实在看不出这个词是在说测试方法。

Re: TDD 既是设计方法,也是测试方法 by Zhang Charlie

键 仝说:

Test-driven development,我实在看不出这个词是在说测试方法。


那么,请问你“实在地”从什么地方看到了 a design method?

我想,你应该看到了三个词:test, driven 和 development。

难道“Test-driven development” 的 development 里面只有 design?

实际上完整的 TDD 是一个开发的循环,它的 development 即包括 test(如何写 test,如何执行 test,如何提高测试的质量,如何用测试来驱动设计等等), 也包括 design,也包括编码,也包括 refactoring(对原先设计的重构)等等 ...

显然 TDD 开发中包括了 Kent Beck 推荐的测试原则、测试思想和测试方法

所以,“TDD 不是测试方法”是片面的。毫无疑问 TDD 包含了测试方法,这是一个简单的逻辑推理。

推荐你去看原版书吧。

敏捷教练 张恂
www.zhangxun.com

Re: TDD 既是设计方法,也是测试方法 by Tong James

唉,确实争论这个也没用,多余的也不想说了。最后发一贴,给旁听生看。

测试驱动开发,不用看原版书,仅从单词上和楼上的阐述出发这也是个设计方法,书里面写的测试方法多,只能说明测试很重要。我们用TDD是为了什么?目的还不是更好的设计,难不成是更好的测试?TDD是一个方法,它是为了解决开发中的问题被提出,是为了解决开发中的什么问题?是设计问题还是测试问题?“不是测试方法”和“包含测试方法”并不矛盾,这也没什么逻辑问题。确实,更合适的测试方法可以更好的驱动开发。但不能因此就把它归结到测试方法里去。(这也是我说争论没意思的原因,争来争去为了一个归类,重在交流吧。)

TDD 既为了更好的设计,也为了更好的测试 by Zhang Charlie

我想,TDD 到底是设计方法,还是测试方法,这不仅仅是一个归类的问题,其实是一个对 TDD 本质准确理解的问题,我知道国内不少人对此有误解,谬误流传已久,所以我才提出来讨论。

有人说,“TDD 不是测试方法”,就很可能忽略掉了经典 TDD 其实是一种单元测试驱动的开发/测试方法这个本质特征。孤零零的单元测试驱动,与其他的交互测试驱动、功能测试驱动等等测试方法显然是不同的。

键 仝说:

我们用 TDD 是为了什么?目的还不是更好的设计,难不成是更好的测试


您说对了,两个都是 TDD 的目标,而且更好的设计,是为了更好的测试,为了便于测试而修改设计,这是 Kent Beck 的本意吧。

键 仝说:

TDD是一个方法,它是为了解决开发中的问题被提出,是为了解决开发中的什么问题?是设计问题还是测试问题?


TDD 首先解决测试问题,然后解决设计问题。

TDD 还有一个名称:Test-first development。

正是因为 Kent Beck 觉得单元测试很重要,而过去许多程序员单元测试做得很差,甚至不愿写单元测试,都认为测试是 QA 的事,导致程序质量很差,所以 Kent Beck 才和 Eric Gamma 一道开发了一个非常方便的配套工具 JUnit,并命名了测试优先方法,可以看出他对测试方法、测试重要性的强调。

为什么要测试优先,测试驱动?是为了让你的代码、设计,更好地服务于测试,更易于测试,从而提高软件质量!

以上我说的这些来龙去脉和背景知识,不是什么新闻,已经是敏捷社群的共识了吧。

通过实施测试优先的 TDD,也就是推广 developer-test,测试的强度和覆盖率都显著提高了。这就是 TDD 带来的一大好处。

TDD 是一种以测试为中心的工程方法,其中既包括设计方法,也包括测试方法,是两者的有机集成,我想这种说法是比较科学准确的。

敏捷 OO 教练 张恂
www.zhangxun.com

Re: TDD 既为了更好的设计,也为了更好的测试 by Jacky Li

>为什么要测试优先,测试驱动?是为了让你的代码、设计,更好地服务于测试,更易于测试,从而提高软件质量!

服了,喵喵的

>共识

您再拉几个人来说TDD是测试方法看看?

凉粉 小刀应该就是本站敏捷首席李剑吧! by Zhang Charlie


2008年2月25日 上午7时41分 发表人 凉粉 小刀

>共识

您再拉几个人来说TDD是测试方法看看?


如果你是敏捷首席,你应该知道,一个科学客观的结论:“TDD 到底是不是测试方法”,不是由投票人数的多少来决定的。

您这个建议有点外行了。

(附:在同一个坛子里,有必要弄两个帐号吗,一个大名,一个小名,便于切换?)

敏捷 OO 教练 张恂
www.zhangxun.com

Re: 凉粉 小刀应该就是本站敏捷首席李剑吧! by Jacky Li

>在同一个坛子里,有必要弄两个帐号吗,一个大名,一个小名,便于切换?

faint了,我倒是从来都没掩藏过身份,用网名来回帖灌水,这个难道不正常么?

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

13 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT