Disadvantages of Test Driven Development?采用测试驱动设计会给我带来什么损失? 只列出底片; 不要列出以负面形式写的福利。 如果要进行"真实的" TDD(请阅读:首先使用红色,绿色和重构步骤进行测试),那么当您要测试集成点时,还必须开始使用模拟/存根。 当您开始使用模拟时,过一会儿,您将要开始使用依赖注入(DI)和控制反转(IoC)容器。为此,您需要对所有内容使用接口(本身有很多陷阱)。 最终,您必须编写更多的代码,而不是仅仅按照"普通的旧方法"编写代码。您不仅需要编写一个客户类,还需要编写一个接口,一个模拟类,一些IoC配置和一些测试。 请记住,测试代码也应该维护和保养。测试应该与其他所有内容一样可读,并且需要花费时间来编写好的代码。 许多开发人员不太了解如何"正确地"完成所有这些操作。但是因为每个人都告诉他们TDD是开发软件的唯一真实方法,所以他们会尽力而为。 这比人们想象的要难得多。通常,使用TDD完成的项目最终会产生很多真正没人能理解的代码。单元测试通常会测试错误的东西,错误的方式。没有人同意好的测试应该是什么样子,甚至没有所谓的专家。 所有这些测试使"更改"(与重构相反)系统行为变得更加困难,简单的更改变得非常困难且耗时。 如果您阅读TDD文献,总是会有一些很好的例子,但是在现实生活中的应用程序中,通常必须有一个用户界面和一个数据库。这是TDD变得非常困难的地方,而且大多数资料来源都没有提供好的答案。如果这样做的话,它总是涉及更多的抽象:模拟对象,接口编程,MVC / MVP模式等,这又需要大量的知识,并且...您必须编写更多的代码。 所以要小心...如果您没有一支热情的团队,但至少没有一位经验丰富的开发人员,他们知道如何编写良好的测试,并且还了解一些有关良好体系结构的知识,那么在走TDD之路之前,您确实必须三思而行。 。 有几个缺点(我并没有声称没有好处-特别是在编写项目基础时-最终会节省很多时间):
当您达到大量测试的地步时,更改系统可能需要重新编写部分或全部测试,具体取决于那些更改使测试无效。这可能会使相对快速的修改变成非常耗时的修改。 而且,您可能开始更多地基于TDD而不是实际上是好的设计原则来做出设计决策。尽管您可能有一个非常简单,容易的解决方案,无法测试TDD的要求,但您现在拥有了一个更为复杂的系统,实际上更容易出错。 我认为对我来说最大的问题是"投入"大量的时间。我仍然非常热爱TDD(如果您有兴趣,请参阅我的博客以获取更新我的测试历程)的开始,而我实际上已经花了数小时来开始。 使您的大脑进入"测试模式"需要很长时间,而编写"可测试的代码"本身就是一项技能。 TBH,我谨不同意杰森·科恩(Jason Cohen)关于公开私有方法的评论,这不是事实。在我的新工作方式中,我没有比以前更多的公开方法了。但是,它确实涉及架构更改,并允许您"热插拔"代码模块,以使其他所有内容更易于测试。您不应该使代码的内部更易于访问。否则,我们将回到一切公开的状态,其中的封装在哪里? 因此,(IMO)简而言之:
PS:如果您想链接到肯定的链接,我已经询问并回答了几个问题,请查看我的个人资料。 在我从事"测试驱动开发"的几年中,我不得不说最大的缺点是: 卖给管理层
卖给其他开发商
维护测试代码和生产代码
编写测试,以便涵盖所有内容(100%的代码覆盖率)
但是,我要说的是,TDD的好处远远超过了一个简单的想法的负面影响:如果您可以实现一组涵盖您的应用程序的良好测试,但又不那么脆弱,以至于一次更改会破坏所有这些测试,您将能够像在第1天一样在项目的第300天继续添加新功能。并非所有尝试TDD的人都认为这是所有错误代码的魔术子弹,因此他们认为可以工作,期间。 我个人发现使用TDD可以编写更简单的代码,花费更少的时间来讨论某个特定的代码解决方案是否可以工作,并且我不担心更改任何不符合以下条件的代码行:团队。 TDD是一门很难掌握的学科,我从事这门课程已经有几年了,我仍然一直在学习新的测试技术。这是一笔巨大的时间投资,但从长远来看,与没有自动化的单元测试相比,您的可持续性将大大提高。现在,如果只有我的老板能弄清楚这一点。 在您的第一个TDD项目中,有两个重大损失,时间和个人自由 您浪费时间是因为:
您失去个人自由是因为:
希望这可以帮助 TDD要求您在编写代码通过这些测试之前,计划一下类将如何运行。这是一个加号和一个减号。 我发现在编写任何代码之前很难在"真空"中编写测试。根据我的经验,每当我不可避免地在编写类时却想到一些在编写初始测试时忘记了的东西时,我都会跳过测试。然后是时候不仅重构我的类,还重构我的测试了。重复三到四次,可能会令人沮丧。 我更喜欢先编写课程草稿,然后编写(并维护)一系列单元测试。草稿后,TDD对我来说很好。例如,如果报告了一个错误,我将编写一个测试以利用该错误,然后修复代码,以便测试通过。 使用TDD进行原型设计可能会非常困难-当您不确定要走解决方案的路时,预先编写测试可能很困难(除了非常广泛的测试之外)。可能会很痛苦。 老实说,我认为对于绝大多数项目而言,"核心开发"并没有任何实质性的弊端。通常,人们认为自己的代码足够好以至于不需要测试(从来没有),而那些纯朴的人也不会为编写它们而烦恼。 好了,这需要您调试测试。同样,编写测试会花费一定的时间,尽管大多数人都认为这是一项前期投资,可以在节省时间的调试和稳定性方面在应用程序的生命周期内获得回报。 不过,我个人遇到的最大问题是,要学会纪律以实际编写测试。在团队中,尤其是已建立的团队中,很难说服他们花费的时间是值得的。 如果您的测试不是很彻底,您可能会因为测试通过而陷入"一切正常"的错误感觉。从理论上讲,如果您的测试通过了,则说明代码有效。但是,如果我们可以在第一时间完美编写代码,就不需要测试。这里的道义是要确保在调用完整的东西之前自己做一个健全性检查,而不仅仅是依靠测试。 关于这一点,如果您的健全性检查发现未测试的内容,请确保返回并为其编写测试。 TDD的不利之处在于,它通常与"敏捷"方法紧密相关,该方法不重视系统文档,而是理解为什么测试"应该"返回一个特定值而不是其他任何值仅存在于开发人员的头。 一旦开发人员离开或忘记了测试返回一个特定值而不返回其他特定值的原因,您就被搞砸了。如果TDD充分记录在案,并且周围环绕着人类可读的文件(即,尖尖的经理),则可以在5年内(当世界变化且您的应用也需要使用它时)进行引用。 当我谈到文档时,这不是代码的模糊,而是应用程序外部存在的官方书面材料,例如用例和背景信息,经理,律师和需要更新的可怜树液可以参考这些信息您的代码在2011年。 我遇到过几种情况,TDD使我发疯。列举一些:
最大的问题是不知道如何编写适当的单元测试的人。他们编写了彼此依赖的测试(并且与Ant一起运行时效果很好,但是当我从Eclipse运行它们时,突然突然失败了,只是因为它们以不同的顺序运行)。他们编写的测试不会对任何东西进行特别的测试-他们只是调试代码,检查结果,然后将其更改为test,将其称为" test1"。它们扩大了类和方法的范围,只是因为为它们编写单元测试会更容易。单元测试的代码非常糟糕,存在所有经典的编程问题(繁重的耦合,500行长的方法,硬编码的值,代码重复),并且难以维护。由于某些奇怪的原因,人们将单元测试视为劣于"真实"代码,并且根本不在乎其质量。 :-( 在测试所有代码之前,您将失去说自己"完成"的能力。 您将失去在运行之前编写数百或数千行代码的能力。 您会失去通过调试学习的机会。 您将失去不确定的代码发布灵活性。 您失去了紧密耦合模块的自由。 您将失去跳过编写低级设计文档的选项。 您将失去每个人都不敢更改的代码所带来的稳定性。 您失去了"黑客"的头衔。 您会浪费大量时间来编写测试。当然,这可以在项目结束时通过更快地捕获错误来保存。 最大的缺点是,如果您确实想正确执行TDD,则在成功之前必须失败很多。鉴于有多少家软件公司在工作(按KLOC美元计),您最终将被解雇。即使您的代码更快,更干净,更易于维护且漏洞更少。 如果您在一家由KLOC支付报酬的公司(或已实施的要求-即使未经测试),请远离TDD(或代码审查,结对编程,或持续集成等)。 我第二次回答有关初始开发时间的问题。您还会失去在没有测试安全性的情况下舒适地工作的能力。我也被描述为TDD坚果吧,所以您可能会失去几个朋友;) 人们认为它慢一些。从长远来看,这不是很悲痛,因为它可以使您免于沉迷,但是最终您将编写更多的代码,因此可以说您将时间花在"测试非编码"上。这是一个有缺陷的论点,但您确实提出了! 重新关注困难的,不可预见的需求是程序员的祸根。测试驱动的开发迫使您将精力集中在已知的普通需求上,并将您的开发限制在已经想到的范围内。 考虑一下,您很可能最终会针对特定的测试用例进行设计,因此您将不会有创造力,而是开始思考"如果用户可以执行X,Y和Z,那将很酷"。因此,当用户开始对潜在的散热要求X,Y和Z感到兴奋时,您的设计可能过于严格地专注于已经指定的测试用例,并且将很难进行调整。 当然,这是一把双刃剑。如果您花费所有时间为用户可能想要的每种可能的,可想象的X,Y和Z进行设计,那么您将不可避免地永远不会完成任何事情。如果您完成了某些工作,那么任何人(包括您自己)都将不可能知道您在代码/设计中正在做什么。 一切都很好。我将添加一些方法来避免TDD的阴暗面:
为诸如XML提要和数据库之类的"随机"数据编写测试可能很困难并且很耗时(不是那么困难)。我最近花了一些时间来处理天气数据供稿。至少因为我没有太多的TDD经验,这使编写测试相当混乱。
您将失去承担多个职责的大班课程。
杰森·科恩(Jason Cohen)说了些类似的话: 我说这表示缺少抽象-如果确实需要测试私有代码,则可能应该在单独的类中。 戴夫·曼 您必须以不同的方式编写应用程序:一种使其可测试的方法。首先,您会感到惊讶,这很困难。 有些人发现了在写得太难之前先考虑要写什么的概念。嘲笑之类的概念对于某些人来说也可能很难。如果不是为测试而设计的,则旧版应用中的TDD可能会非常困难。围绕不兼容TDD的框架进行TDD也可能会很困难。 TDD是一项技能,因此初级开发人员起初可能会遇到困难(主要是因为尚未教会他们这种工作方式)。 总体而言,尽管随着人们的熟练程度而解决了弊端,但您最终还是抽象出了"臭味"代码,并拥有了更稳定的系统。
在项目中花一些时间才能开始使用它,但是...当我发现自动测试可以很快发现的愚蠢错误时,我总是后悔没有采用"测试驱动"方法。另外,TDD提高了代码质量。 您必须确保测试始终是最新的,开始忽略红灯的那一刻就是测试变得毫无意义的那一刻。 您还必须确保测试是全面的,否则当出现大错误时,您最终说服您花费时间编写更多代码的闷热管理类型就会抱怨。 教我团队敏捷开发的人不相信计划,您只写了最小的要求。 他的座右铭是重构,重构,重构。我了解到重构意味着"不提前计划"。 让我补充一下,如果将BDD原理应用于TDD项目,则可以缓解此处列出的一些主要缺点(混乱,误解等)。如果您不熟悉BDD,则应阅读Dan North的介绍。他提出这个概念是为了回答在工作场所应用TDD所引起的一些问题。 Dan的BDD简介可以在这里找到。 我之所以提出这一建议,是因为BDD解决了其中的一些负面问题,并起到了一定的作用。您需要在收集反馈时考虑这一点。
TDD需要您的代码的特定组织。这可能效率低下或难以阅读。甚至在架构上是错误的;例如,由于不能在类外调用
当代码更改时,您还必须更改测试。通过重构,这可能是一个 开发时间增加:每种方法都需要测试,并且如果您有一个具有依赖项的大型应用程序,则需要准备和清理数据以进行测试。 您将失去进行增量更改(代码重构)的能力,并且仍然对代码执行预期的工作感到热情和模糊。您几乎没有自由和轻松的动力来以最少的显式依赖关系构造代码。 IOW,您将能够嵌入很多依赖关系而无需注意。如果您使用TDD,则在编写测试时依赖项将显示为痛苦/气味。 |