测试驱动开发的缺点?[关闭]


192

采用测试驱动设计会给我带来什么损失?

仅列出底片;不要列出以负面形式写的福利。


我添加了一个答案,指出BDD可以缓解其中的一些负面影响。我敦促您在收集负输入时考虑此因素,因为其中一些可以消除并且不再视为负输入。
Kilhoffer

25
为了澄清,我不反对也不赞成。我正在尝试就此事做出明智的决定,但大多数主张TDD的人不理解,或不愿接受负面意见。
IanL

1
标题提到“测试驱动开发”,但问题的正文提到“测试驱动设计”。这个问题是关于两个的?两者之间存在重要但细微的差异。测试驱动的设计是关于让测试驱动软件的设计。测试驱动的开发通常与在生产代码之前编写测试相关联(但不一定让测试影响设计)。
Jim Hurne,2011年

3
TDD是一个保留开发人员创造力的笼子。
刘易斯

13
请停止结束重要的问题,djesus
卡斯珀·莱昂·尼尔森

Answers:


129

有几个缺点(我并不是说没有好处-特别是在编写项目基础时-最终会节省很多时间):

  • 大量的时间投入。对于简单的情况,您损失了大约20%的实际实现,但是对于复杂的情况,您损失了更多。
  • 额外的复杂性。对于复杂的案例,您的测试案例很难计算,我建议在这种情况下尝试使用自动参考代码,该代码将在调试版本/测试运行中并行运行,而不是最简单案例的单元测试。
  • 设计影响。有时,设计一开始并不清楚,并且会随着您的发展而不断发展-这将迫使您重做测试,这会浪费大量时间。我建议在这种情况下推迟单元测试,直到您对设计有所了解。
  • 连续调整。对于数据结构和黑匣子算法,单元测试将是完美的,但是对于倾向于更改,微调或微调的算法,这可能会导致大量的时间投入,而人们可能会认为这是不合理的。因此,当您认为它确实适合系统并且不要强迫设计适合TDD时,请使用它。

7
要点(4)是-任何定义不明确且可能会不断变化以适应不断发展的视觉行为,不同的AI规范,行为算法等的系统。由于我们一直坚持不懈地进行重复测试定义,因此会花费大量时间更改所需的测试结果。
阿迪

12
是的,但是没有TDD会不会一样?没有它,您将不得不进行更多的手动测试,这将遇到相同的问题。
sleske 2010年

50
在开发解决方案时,“大笔投资”是否可以节省您以后的时间?特别是复杂的?我想这应该可以节省您的时间。不要考虑维护阶段,在此阶段进行小的更改很容易破坏系统。(或者我只是天真地对待防止将来发生错误的单元+回归测试
Robert Koritnik 2010年

6
Sergio / Robert,我非常赞成对通用系统以及绝对是代表系统基础的组件进行单元测试。话虽如此,我想补充一点,就是需要试图声称每个系统都可以用这种方式来区分这些情况和过分简化现实生活。并非所有系统都可以针对单元测试进行通用化和简化,并且如果您试图在此类系统上强制进行单元测试,那么与实际测试实际结果相比,您很容易花费更多的时间来更正单元测试。
2014年

3
@Adi:我认为你错了。我认为,每个系统都可以通过这种方式进行测试,这只是自律的问题。
BlueLettuce16 2015年

189

如果要进行“真实的” TDD(请阅读:首先使用红色,绿色和重构步骤进行测试),那么当您要测试集成点时,还必须开始使用模拟/存根。

当您开始使用模拟时,过一会儿,您将要开始使用依赖注入(DI)和控制反转(IoC)容器。为此,您需要对所有内容使用接口(本身有很多陷阱)。

最终,您必须编写更多的代码,而不是仅仅按照“简单的旧方法”编写代码。您不仅需要编写一个客户类,还需要编写一个接口,一个模拟类,一些IoC配置和一些测试。

请记住,测试代码也应该维护和保养。测试应该与其他所有内容一样易读,并且编写好的代码需要时间。

许多开发人员不太了解如何“正确地”完成所有这些操作。但是因为每个人都告诉他们TDD是开发软件的唯一真实方法,所以他们会尽力而为。

这比人们想象的要难得多。通常,使用TDD完成的项目最终会产生很多真正没人能理解的代码。单元测试经常测试错误的东西,错误的方式。没有人同意好的测试应该是什么样子,甚至没有所谓的专家。

所有这些测试使“更改”(与重构相反)系统行为变得更加困难,简单的更改变得非常困难且耗时。

如果您阅读TDD文献,总是会有一些很好的例子,但是在现实生活中的应用程序中,通常必须有一个用户界面和一个数据库。这是TDD变得非常困难的地方,而且大多数资料来源都没有提供好的答案。如果这样做的话,它总是涉及更多的抽象:模拟对象,接口编程,MVC / MVP模式等,这又需要大量的知识,并且...您必须编写更多的代码。

所以要小心...如果您没有一支热情的团队,但至少没有一位经验丰富的开发人员,他们知道如何编写良好的测试,并且还了解一些有关良好体系结构的知识,那么在走TDD之路之前,您确实必须三思而行。 。


7
使用Pex&Moles之类的工具您可以非常轻松地避免为每件该死的小事编写界面。痣将极大地帮助您。
罗伯特·科里特尼克

24
似乎是单元测试和面向对象编程的疯狂,而不是TDD。
plmaheu

5
实际上正确的“单元测试”(不仅是TDD)还需要模拟/存根。对接口进行编程通常是一个好主意,对于模式也是如此。如果您将UI和逻辑混在一起,那将是一段糟糕的时光。如果必须测试数据库交互,您仍然可以为单元测试模拟DAO,并使用真实的东西进行集成测试。
TheMorph

1
我同意这样一个事实,那就是在进入tdd之前,人们已经具备了设计和测试的知识。这对于拥有新员工的项目至关重要,因为这两者都是新手。
Hitesh Sahu

投票支持智慧
sabsab

66

当您达到大量测试的地步时,更改系统可能需要重新编写部分或全部测试,具体取决于哪些测试由于更改而无效。这可能会使相对快速的修改变成非常耗时的修改。

同样,您可能开始更多地基于TDD而非真正好的设计原则来做出设计决策。尽管您可能有一个非常简单,简单的解决方案,无法测试TDD的要求,但您现在拥有了一个更加复杂的系统,实际上更容易出错。


3
绝对可能是一个问题,但是我发现我受此影响的程度有显着差异。我猜这全都归结为“编写可测试的代码”。
罗伯·库珀,

2
斯科特,我通常给出的示例是嵌入在ASPX页面中的SqlDataSource。您无法为此自动化测试。它很简单,只需1个文件即可完成工作。可测试的组件是MSFT的SqlDataSource对象,已经为我们完成了。无需我们做更多的事情。
Eric Z Beard

8
+1“您可能会开始更多地根据TDD而不是实际上是好的设计原则来做出设计决策”-TDD IMHO的最大陷阱。
2011年

2
@ScottSaad IMO的问题是应首先概述设计,然后应通过编写测试进行验证并在需要时进行更正。我见过很多情况,当人们为了编写测试而危及良好的设计时。结果-大多数系统都经过测试,但是设计确实很丑陋。我认为这是因为TDD作为一种非常简单的方法推向大众并带有以下误解if part of the system is covered by tests and they pass, then everything is fine (including design)
Yuriy Nakonechnyy 2014年

3
@Yura:有趣的是,人们为了编写测试而在危及良好的设计。我认为,如果有一个好的设计,就没有必要破坏它。我曾经见过这样的项目,而代码库却是一场噩梦,但人们却认为相同-设计很棒。我只同意将TDD作为一种非常简单的方法推向大众这一部分,但这是完全相反的。在我看来,当代码设计良好时,然后进行一些小的更改,就没有机会阻止所有测试或大量测试。
BlueLettuce16 2015年

54

我认为对我来说最大的问题是“投入”大量的时间。我仍然非常热爱TDD(如果您有兴趣的话,请参阅我的博客以获取更新我的测试历程)的开始,而我实际上已经花费了数小时来入门。

使您的大脑进入“测试模式”需要很长时间,而编写“可测试的代码”本身就是一项技能。

TBH,我谨对此表示不同意,Jason Cohen关于公开私有方法的评论并非如此。在我的新工作方式中,我没有比以前更多的公开方法了。但是,它确实涉及架构更改,并允许您“热插拔”代码模块,以使其他所有内容更易于测试。您应该使代码的内部更易于访问。否则,我们将回到一切公开的状态,其中的封装在哪里?

因此,(IMO)简而言之:

  • 思考所花费的时间(即实际在测试中)。
  • 知道如何编写可测试代码所需的新知识。
  • 了解使代码可测试所需的体系结构更改。
  • 在尝试提高我们出色的编程技巧所需的所有其他技能的同时,提高您的“ TDD编码器”技能:)
  • 组织您的代码库以包括测试代码,而不会花费您的生产代码。

PS:如果您想获得肯定的链接,我已经询问并回答了几个问题,请查看我的个人资料


1
不幸的是,我看到的第一个合理答案是……
丹尼尔·C·索布拉尔2012年

5
十分实用且简单的答案-为“思维设置”部分+1
ha9u63ar 2013年

50

在我从事测试驱动开发的几年中,我不得不说最大的缺点是:

卖给管理层

TDD最好成对完成。例如,当您知道如何编写if / else语句时,很难抵制只编写实现的冲动。但是一对会让您继续执行任务,因为您让他继续执行任务。可悲的是,许多公司/经理并不认为这是对资源的良好利用。当我同时需要完成两项功能时,为什么要花两个人来编写一项功能?

卖给其他开发商

有些人只是没有耐心编写单元测试。有些人为他们的工作感到骄傲。或者,有些就像看到复杂的方法/功能从屏幕末端流了出来。TDD并非适合所有人,但我真的希望如此。对于那些继承代码的可怜的灵魂来说,这将使维护工作变得更加容易。

维护测试代码和生产代码

理想情况下,仅当您做出错误的代码决策时,测试才会中断。也就是说,您认为系统以一种方式工作,但事实却并非如此。通过破坏一个测试或一组(少量)测试,这实际上是个好消息。您确切地知道您的新代码将如何影响系统。但是,如果您的测试写得不好,耦合紧密,或者更糟糕的是生成了(咳嗽 VS测试),那么保持测试可以很快成为合唱团。并且,在足够多的测试开始进行更多工作以达到他们所创造的感知价值之后,当日程安排变得压缩时(例如,时间变得紧迫),这些测试将是首先要删除的东西。

编写测试,以便涵盖所有内容(100%的代码覆盖率)

再次,理想情况下,如果您遵循该方法,则默认情况下将对您的代码进行100%的测试。通常,以为,我最终得到的代码覆盖率高达90%。当我拥有一些模板样式架构,并且已经测试了基础,并且尝试偷工减料而不测试模板定制时,通常会发生这种情况。另外,我发现当我遇到以前从未遇到过的新障碍时,我在测试它时会遇到学习障碍。我承认我会以传统的笨拙方式编写一些代码行,但我真的很喜欢100%的代码。(我想我在学校里是个超卓成就者,er skool)。

但是,我要说的是,TDD的好处远远超过了一个简单的想法的缺点,即如果您可以实现涵盖您的应用程序的一组好的测试,但又不那么脆弱,以至于一次更改会破坏所有这些测试,您将能够像在第1天一样在项目的第300天继续添加新功能。并非所有尝试TDD的人都认为这是所有错误代码的魔术子弹,因此他们认为可以工作,期间。

我个人发现使用TDD可以编写更简单的代码,花费更少的时间来讨论某个特定的代码解决方案是否可以工作,并且我不担心更改任何不符合以下条件的代码行:团队。

TDD是一门很难掌握的学科,我从事这门课程已经有几年了,我仍然一直在学习新的测试技术。这是一笔巨大的时间投资,但是从长远来看,与没有自动化的单元测试相比,您的可持续性将大大提高。现在,如果只有我的老板能弄清楚这一点。


7
以“(咳嗽VS测试),然后是主要”结尾的句子的其余部分是什么?
安德鲁·格林

+1为销售问题。:)我现在在一家新公司里,正在思考如何建立一种文化,使技能可以自由传播。
Esko Luontola 2011年

2
正如您所看到的,我认为一些顾问公司正在利用结对编程和TDD来从客户那里获得更多收益。这些客户如何为乍看之下似乎很合理的想法付钱,例如两个人认为比2好得多,或者TDD确保测试了每一行代码,但最终他们只是让客户付钱的借口,这真是令人失望仅需一个人就能完成的工作。
lmiguelvargasf '16

24

在您的第一个TDD项目中,有两个重大损失,时间和人身自由

您浪费时间是因为:

  • 创建一个全面的,可重构的,可维护的单元测试和验收测试套件可以为项目的第一次迭代增加大量时间。从长远来看,这可能可以节省时间,但同样地,您也可以节省时间。
  • 您需要选择一套核心工具并成为专家。单元测试工具需要某种模拟框架的补充,并且两者都必须成为自动化构建系统的一部分。您还希望选择并生成适当的指标。

您失去个人自由是因为:

  • TDD是一种非常有纪律的代码编写方式,往往会与技能等级最高和最低的人产生摩擦。始终以某种方式编写生产代码并使您的工作受到不断的同行审查可能会吓到您最糟糕和最好的开发人员,甚至导致人员减少。
  • 嵌入TDD的大多数敏捷方法都要求您不断与客户讨论您打算完成的工作(在本故事中/每天/无论如何)以及权衡取舍。再一次,这不是每个人都可以喝的茶,无论是在围栏的开发者方面还是在客户方面。

希望这可以帮助


1
我不知道这是因为我是最坏的还是最好的..但是TDD却使我误解了。这是因为它迫使我过早进入双重维护模式。每次更改类的设计时,现在都必须更改测试用例。我期望并接受来自成熟班级的建议,但不能接受我上周刚刚写的课程!我也可以说Java和C#等语言对DI和TDD的支持不佳。确实有人需要创建一种新的语言,以便TDD和DI的成本实际上为零。然后,我们将不再有此对话。
John Henckel

14

TDD要求您在编写代码通过这些测试之前,计划一下类将如何运行。这既是加号也是减号。

我发现在编写任何代码之前很难在“真空”中编写测试。根据我的经验,每当我不可避免地在编写类时却想到一些在编写初始测试时忘记了的东西时,我都会跳过测试。然后是时候不仅重构我的类,还重构我的测试了。重复三到四次,可能会令人沮丧。

我更喜欢先编写课程草稿,然后编写(并维护)一系列单元测试。草稿后,TDD对我来说很好。例如,如果报告了一个错误,我将编写一个测试以利用该错误,然后修复代码,以便测试通过。


1
尽管您应该对系统的体系结构有所了解,但是在进行TDD时并不需要提前了解很多。TDD意味着测试会驱动设计,因此随着您实施更多测试方案,它会发生变化
casademora

4
我同意真空。TDD的原始教程非常疯狂,您无需编写任何代码即可编写测试,并且会遇到编译错误。
mparaz

错误的假设是您只能编写一次测试,并且不能更改它们。它们是代码,更改后,每个代码最终都需要重构。测试也不例外。如果要保持测试的可维护性,则必须进行重构测试。
Roman Konoval

12

使用TDD进行原型设计可能会非常困难-当您不确定要走解决方案的路时,预先编写测试可能很困难(除了非常广泛的测试之外)。可能会很痛苦。

老实说,我认为对于绝大多数项目而言,“核心开发”并没有任何实质性的弊端。通常,人们认为自己的代码足够好以至于不需要测试(从来没有),而那些纯朴的人也不会为编写它们而烦恼。


9

好了,这需要您调试测试。同样,编写测试会花费一定的时间,尽管大多数人都认为这是一项前期投资,可以在节省时间的调试和稳定性方面在应用程序的生命周期内获得回报。

但是,我个人遇到的最大问题是要提高纪律以实际编写测试。在团队中,尤其是已建立的团队中,很难说服他们花费的时间是值得的。


13
啊哈-但这就是TDTDD的用武之地。测试驱动测试驱动开发。
Snowcrash 2013年

3
我仍然偶尔在测试测试中发现错误。所以现在我练习TDTDTDD。
HorseloverFat 2014年

@SnowCrash +1我环顾Google,了解人们花了多少时间测试自己的测试,然后我看到了这个答案。我之所以正式找到它,是因为我想知道TDTDTDD。
BalinKingOfMoria恢复CM 2015年

1
我相信未来是(TD)<sup>∞</ sup> TDD。到目前为止,我有一个文件:它包含字母“ x”。
麦克啮齿动物,

我同意@Tim。说服成员采用它是最困难的部分。
奥卢·史密斯

7

如果您的测试不是很彻底,您可能会因为测试通过而陷入一种“一切正常”的错误观念。从理论上讲,如果您的测试通过,则代码可以正常工作;但是,如果我们可以在第一时间完美编写代码,就不需要测试。这里的道义是确保在调用完整的内容之前自己进行完整性检查,而不仅仅是依靠测试。

关于这一点,如果您的健全性检查发现未测试的内容,请确保返回并为其编写测试。


自从我长大以来,我不相信没有理智的条款。
麦克啮齿动物

7

TDD的缺点是,它通常与“敏捷”方法紧密相关,该方法重视系统文档,而是理解为什么测试“应该”返回一个特定值而不是其他任何值仅存在于开发人员的头。

一旦开发人员离开或忘记了测试返回一个特定值而不返回其他特定值的原因,您就被搞砸了。如果已充分记录了TDD,并使用了易于理解的文档(例如,尖尖的经理),则可以在5年内(当世界变化且您的应用也需要使用它时)引用TDD。

当我谈论文档时,这不是代码的模糊,而是应用程序外部存在的官方书面材料,例如用例和背景信息,经理,律师和需要更新的可怜树液可以参考这些信息您的代码在2011年。


1
完美地放。我完全同意。对我来说,测试当然无助于描述现实世界中更高层次的问题定义。好的文档一次又一次地证明了它的价值。作为技术。随着行业的发展,经过时间考验的概念应更加谨慎。自我记录代码是一个荒谬的概念。我确实相信原型,重构和敏捷性一开始就不会定义问题。但是,具有讽刺意味的是,一开始并没有过分定义问题,因此将TDD存根成为雷区。
wax_lyrical

1
我认为这是不公平的。良好的TDD做法谴责魔术数字和晦涩难懂的测试。测试应该比您的生产代码本身简单,并且最好具有可读性。您的测试是文档。确保它们看起来像它。这个答案有点像说“文档化是邪恶的,因为人们有时会写出非常糟糕的文档”或“类是不良的,因为我已经看到一些难以处理的上帝类”。
萨拉

6

我遇到过几种情况,TDD使我发疯。列举一些:

  • 测试用例的可维护性:

    如果您在大型企业中,很多机会是您不必自己编写测试用例,或者至少当您进入公司时,其中大多数是由其他人编写的。应用程序的功能会不时更改,如果没有适当的系统(例如HP Quality Center)来跟踪它们,您将很快发疯。

    这也意味着新团队成员需要大量时间来掌握测试用例的进展。反过来,这可以转化为更多的资金需求。

  • 测试自动化的复杂性:

    如果将部分或全部测试用例自动化到机器可运行的测试脚本中,则必须确保这些测试脚本与其相应的手动测试用例保持同步,并且与应用程序更改保持一致。

    另外,您将花费时间调试有助于捕获错误的代码。我认为,这些错误中的大多数来自测试团队未能在自动化测试脚本中反映应用程序更改。业务逻辑,GUI和其他内部内容的更改会导致脚本停止运行或运行不可靠。有时这些变化非常微妙,难以检测。一旦我的所有脚本都报告失败,因为它们的计算基于表1的信息,而表1现在是表2(因为有人在应用程序代码中交换了表对象的名称)。


这与TDD完全无关。如果其他部门的其他人正在编写您的测试用例,则您不是在进行TDD。如果您有手动测试用例,则说明您没有在做TDD。如果您的库代码由于GUI更改而中断并且测试失败,则您也很可能也没有进行TDD。这似乎更像是针对无效的大型企业质量检查部门的争论。
萨拉

5

最大的问题是不知道如何编写适当的单元测试的人。他们编写了相互依赖的测试(并且与Ant一起运行时效果很好,但是当我从Eclipse运行它们时,突然突然失败了,只是因为它们以不同的顺序运行)。他们编写的测试不会对任何东西进行特别的测试-他们只是调试代码,检查结果,然后将其更改为test,将其称为“ test1”。它们扩大了类和方法的范围,只是因为为它们编写单元测试会更容易。单元测试的代码非常糟糕,存在所有经典的编程问题(重耦合,500行长的方法,硬编码的值,代码重复),难以维护。由于某些奇怪的原因,人们将单元测试视为劣于“真实”代码,而他们却没有 根本不在乎它们的质量。:-(


4

您会浪费大量时间来编写测试。当然,这可以在项目结束时通过更快地捕获错误来保存。


这是肯定的否定还是狡猾的方式表示肯定。
IanL

3

最大的缺点是,如果您确实想正确执行TDD,则必须先失败很多,然后才能成功。鉴于有多少软件公司在工作(按KLOC美元计),您最终将被解雇。即使您的代码更快,更干净,更易于维护且漏洞更少。

如果您在一家按KLOC付费的公司(或已实施的要求-即使未经测试)则远离TDD(或代码审查,结对编程,或持续集成等)。


3

在测试所有代码之前,您将失去说自己“完成”的能力。

您将失去在运行之前编写数百或数千行代码的能力。

您失去了通过调试学习的机会。

您将失去不确定的代码发布灵活性。

您失去了紧密耦合模块的自由。

您将失去跳过编写低级设计文档的选项。

您将失去每个人都不敢更改的代码所带来的稳定性。


1
取决于您对“按时交付解决方案”的定义-是“按时交付任何旧的,部分破损的解决方案”还是“按时交付工作解决方案”。您肯定失去了按时交付部分解决方案的功能。就开发速度而言-我喜欢“开始开发到一周的无故障实时部署之间所经过的时间”这一指标。如果您合理地衡量它,甚至很难停止copmlex的一项非TDD工作。
达菲德·里斯

47
-1,这正是OP所不希望的。
erikkallen

1
许多真实的陈述,但是:erikkallen说了什么。-1。
j_random_hacker 2010年

@ j_random_hacker说黑客...哈哈
丹,2010年

只有第三个陈述是合法的“失去了通过调试学习的知识”
YEH

2

我第二次回答有关初始开发时间的问题。您还会失去在没有测试安全性的情况下舒适地工作的能力。我也被描述为TDD坚果吧,所以您可能会失去几个朋友;)


2

人们认为它慢一些。从长远来看,这不是很悲痛,它可以使您免于沉迷,但是最终您将编写更多的代码,因此可以说您将时间花在“测试非编码”上。这是一个有缺陷的论点,但您确实提出了要求!


2

重新关注困难的,不可预见的需求是程序员的祸根。测试驱动的开发迫使您将精力集中在已知的普通需求上,并将您的开发限制在已经想到的范围内。

考虑一下,您很可能最终会针对特定的测试用例进行设计,因此您将不会变得很有创意,并开始思考“如果用户可以执行X,Y和Z,那将很酷”。因此,当用户开始对潜在的散热要求X,Y和Z感到兴奋时,您的设计可能过于严格地专注于已经指定的测试用例,并且将很难进行调整。

当然,这是一把双刃剑。如果您花费所有时间为用户可能想要的每种可能的,可想象的X,Y和Z进行设计,那么您将不可避免地永远不会完成任何事情。如果您完成了某些工作,那么任何人(包括您自己)都将不可能知道您在代码/设计中正在做什么。


考虑一下,您很可能最终会针对特定的测试用例进行设计,因此您将不会变得很有创意,并开始思考“如果用户可以执行X,Y和Z,那将很酷”。-我认为完全相反。如果编写单元测试,您会怀疑不同的业务案例,这意味着您很有创造力,并且可以预见无法预料的事情。但是,如果您的实现中存在错误,那么所有的创造力都不重要。
BlueLettuce16 2015年

1

为诸如XML提要和数据库之类的“随机”数据编写测试可能很困难并且很耗时(不是那么困难)。我最近花了一些时间来处理天气数据供稿。至少因为我对TDD没有太多的经验,所以为此编写测试非常令人困惑。


这是一个普遍的问题。我倾向于使用硬编码对象来模拟它们,然后分别测试数据库。然后,您的业务层应仅使用静态数据,然后在受控环境(可以在其中将数据编写脚本等)中对DAL进行测试
Rob Cooper

1

您将失去承担多个职责的大班课程。您也可能会失去承担多个职责的大型方法。您可能会失去一些重构的能力,但是您也会失去一些重构的需求。

杰森·科恩(Jason Cohen)说过类似的话:TDD需要代码的特定组织。这可能在结构上是错误的。例如,由于不能在类外部调用私有方法,因此必须使方法成为非私有方法以使其可测试。

我说这表示缺少抽象-如果确实需要测试私有代码,则可能应该在单独的类中。

戴夫·曼


1

您必须以不同的方式编写应用程序:一种使它们可测试的方法。首先,您会感到惊讶。

有些人发现了在写得太难之前先思考要写什么的概念。嘲笑之类的概念对于某些人来说也可能很难。如果不是为测试而设计的,则旧版应用程序中的TDD可能会非常困难。围绕非TDD友好框架进行TDD也可能会很困难。

TDD是一项技能,因此初级开发人员起初可能会遇到困难(主要是因为尚未教会他们这种工作方式)。

总体而言,尽管随着人们的熟练程度而解决了弊端,但您最终还是抽象出了“臭味”代码,并拥有了更稳定的系统。


1

在项目中花一些时间才能开始使用它,但是...当我发现自动测试本来可以很快发现的愚蠢错误时,我总是后悔没有采用“测试驱动”方法。另外,TDD提高了代码质量。


1
  • 单元测试需要编写更多的代码,因此开发的前期成本更高
  • 需要维护更多代码
  • 需要额外的学习

1

一切都很好。我将添加一些方法来避免TDD的阴暗面:

  • 我已经编写了应用程序来进行自己的随机自检。编写特定测试的问题是,即使您编写了大量测试,它们也只能涵盖您想到的情况。随机测试生成器会发现您没有想到的问题。

  • 大量单元测试的整个概念意味着您拥有的组件可能会进入无效状态,例如复杂的数据结构。如果您远离复杂的数据结构,则要进行的测试要少得多。

  • 在您的应用程序允许的范围内,请避开依赖于通知,事件和副作用的正确排序的设计。这些很容易掉落或混乱,因此需要大量测试。


随机测试可能会间歇性地失败,并使重复测试变得困难
David Sykes

@DavidSykes:无论何时进行随机测试,都要记录参数,这样,如果测试失败,您可以重复进行,或者即使以后没有失败也可以重复进行。关键是它不取决于您思考测试用例。如果您像我一样,本能地倾向于使用安全的测试用例。
Mike Dunlavey 2014年

0

TDD需要您的代码的特定组织。这可能效率低下或难以阅读。甚至在结构上是错误的;例如,由于private不能在类外部调用方法,因此必须使方法成为非私有方法以使其可测试,这是错误的。

当代码更改时,您还必须更改测试。通过重构,这可能会花费很多额外的工作。


9
所有私有方法都应通过仍然存在的公共方法进行测试。
Garry Shutler

这并非对所有类都可行。有时,您不想模拟所有依赖关系等,而只是想测试一个实用程序方法。
杰森·科恩

+1,是真的。除此之外,有时还需要将getter / setter添加到私有字段中,以便能够正确设置和读取单元测试的状态,即使状态对于该类是私有的也是如此。
erikkallen

考虑将测试编写为生活要求文档。然后,您将看到灯光。另请阅读XUnit测试模式。
Scott Nimrod 2014年

0

让我补充一下,如果将BDD原理应用于TDD项目,则可以缓解此处列出的一些主要缺点(混乱,误解等)。如果您不熟悉BDD,则应阅读Dan North的介绍。他提出这个概念是为了回答在工作场所中使用TDD引起的一些问题。Dan的BDD简介可在此处找到。

我之所以提出这一建议,是因为BDD解决了其中的一些负面问题,并起到了一定的作用。您需要在收集反馈时考虑这一点。


绝对。评估TDD时必须考虑BDD。
user9991

似乎BDD =行为驱动的开发
hayalci'Oct

0

您必须确保测试始终是最新的,开始忽略红灯的那一刻就是测试变得毫无意义的那一刻。

您还必须确保测试是全面的,否则当出现大错误时,您最终说服让您花时间编写更多代码的闷闷的管理类型就会抱怨。


0

教我团队敏捷开发的人不相信计划,您只写了最小的要求。

他的座右铭是重构,重构,重构。我了解到重构意味着“不提前计划”。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.