开始TDD - 面临的挑战?解决方案?建议?

43

好的,我知道已经有关于如何开始使用TDD的问题了。然而,我想我知道一般的共识是要就这么做,但是我似乎遇到了以下问题:

  • 在处理集合时,即使基于泛型等“知道”其将起作用的情况下,我们仍会测试明显的添加/删除/插入是否成功吗?
  • 有些测试似乎需要很长时间才能实现..例如,在处理字符串输出时,有没有更好的方法来解决这种情况?(例如,在解析之前测试对象模型,将解析分解为小操作并在那里进行测试)。在我的脑海中,您应该始终测试“最终结果”,但这可能会有很大变化,并且设置起来很麻烦。
  • 我没有测试框架可用(工作不会支付),所以我可以“练习”更多。有哪些免费供商业使用的好的测试框架? (目前我使用老式的Debug.Assert :)
  • 可能最大的问题..有时我不知道预期会发生什么不会。 我的意思是,您会看到绿色的指示灯,但我总是担心可能会错过测试..您会深入挖掘以试图破坏代码,还是让它保持不变并等待它在后来崩溃(这将花费更多时间)。

那么,基本上我在这里寻找的不是“就这么做”,而是更多的“我曾经经历了这些问题,并通过这种方式解决了它们”..个人经验:)

11个回答

50

首先,当你开始尝试在编程风格中使用TDD时,感到沮丧是很正常的。只要不要灰心丧气并放弃,你需要给它一些时间。这是对我们如何思考解决代码问题的一个重大范式转换。我喜欢将其看作是从过程式编程切换到面向对象编程的转变。

其次,我认为测试驱动开发首先是一种设计活动,用于通过创建描述它将公开的API以及如何使用其功能的测试来详细说明组件的设计。测试将帮助塑造和模型化被测试系统,直到您能够封装足够的功能以满足您正在处理的任何任务。

考虑到以上段落,请看看你的问题:

  1. 如果我在被测试的系统中使用了一个集合,则会设置期望,以确保在调用添加项目的方法时代码已被调用,并断言集合的数量。我不一定要测试我的内部列表上的Add方法。我只是确保在调用添加项的方法时已经调用了它。我会将mocking框架与我的测试框架结合使用。
  2. 测试字符串输出可能很烦琐。你无法考虑到每一种结果。你只能根据被测试系统的功能测试你所期望的。你应该总是将测试分解为最小的元素,即只测试它们应该测试的东西,不要测试其他任何东西。
  3. 有很多开源测试框架可供选择。我不会争论哪一个是最好的。只需找到您喜欢的一个并开始使用它。
  • 你可以设置测试来考虑你想要发生的情况。如果出现引入功能漏洞的场景,至少你有一个关于该功能的测试,可以将该场景添加到测试中,然后改变功能直到测试通过。找出我们可能错过测试的方法之一是使用代码覆盖率
  • 在问题一的答案中,我向您介绍了模拟术语。当您引入模拟技术到您的TDD武器库中时,它会大大地使得测试更容易抽象出不属于被测系统的部分。以下是一些可用的模拟框架资源:

    除了阅读关于TDD的过程之外,帮助运用TDD的一种方式是观看其他人实践。我推荐观看JP Boodhoo在DNRTV上的屏幕录像。看看这些:

    好的,这些将帮助你了解我介绍的术语是如何使用的。它还将介绍另一个名为Resharper的工具以及它如何促进TDD过程。在做TDD时,我不建议使用这个工具。看起来你正在学习这个过程,并且只是发现一些已经用其他工具解决的问题。

    如果我没有通过添加Kent Beck在Pragmatic Programmer上关于测试驱动开发的新系列来更新这个内容,我想我会对社区犯下不公平的行为。


    1
    Dale,你的回答真是太棒了伙计!非常清晰简洁,感谢你抽出时间撰写一个非常好的答案。你是明显的赢家! ;) - Rob Cooper
    很棒的回答 - 我无法从JPB网站上获取视频(http下载或银光播放器)。 还有其他地方可以托管这些视频吗? - Rob Allen
    这些视频来自dnrTV。下载后观看可能需要Camtasia视频编解码器。您可以在此处找到它:http://perseus.franklins.net/tscc.exe。 - Dale Ragan
    你可能想要查看这个BDD测试框架:http://nspec.org - Amir

    6

    根据我的经验:

    1. 只测试自己的代码,不需要测试底层框架的代码。所以如果你使用了一个通用列表,就没有必要测试Add、Remove等操作。

    2. 没有第二点。看那边!猴子!!!

    3. NUnit是最佳选择。

    4. 你肯定不能测试每一种情况的结果。我测试我期望发生的事情,然后测试一些边缘情况,其中我期望得到异常或无效响应。如果由于你忘记测试某些内容而导致了错误,那么在尝试修复错误之前,你应该首先编写一个测试来证明该错误存在。


    1
    #3 不太通用于各种编程语言,并且对于不使用C#的人来说也不是很有信息量。 - Andrew Grimm
    @Andrew NUnit绝对是语言无关的。您可以在CLR上使用C#,VB.NET,F#,Boo,Delphi,Cobol等任何编程语言。也许您指的是“平台无关”?无论如何,它不仅限于C#。 - Matt Hamilton
    除了IronRuby之外,Ruby是否使用CLR? - Andrew Grimm
    不,只有IronRuby(它明确是Ruby的CLR版本)。 - Matt Hamilton

    2

    我的观点如下:

    • +1 不要测试框架代码,但您可能仍然需要测试从框架类派生的类。
    • 如果某个类/方法难以测试,则可能暗示着设计存在问题。我尝试遵循“一个类-一个职责,一个方法-一个操作”的原则。通过这种方式,您将能够更轻松地按较小的部分测试复杂的方法。
    • +1 xUnit。对于Java,您还可以考虑TestNG
    • TDD不是单一事件,而是一个过程。因此,请不要试图从一开始就设想所有内容,而应确保发现代码中的每个错误都实际上被测试用例覆盖。

    2
    我认为TDD最重要的事情(实际上也是其中一个伟大的结果)是成功地管理依赖关系。你必须确保模块在测试时是独立的,不需要复杂的设置。例如,如果你正在测试一个最终会发送电子邮件的组件,请将电子邮件发送器作为依赖项,以便你可以在测试中模拟它。 这导致了第二点 - 模拟是你的朋友。熟悉模拟框架及其促进的测试风格(行为测试,而不是经典的状态测试),以及它们鼓励的设计选择("告诉,不要问"原则)。

    2
    我发现在三张索引卡中易于记住TDD的精髓所阐述的原则是一个很好的指南。
    总之,回答你的问题:
    1. 除非你自己写了代码,不然你不需要测试已知会成功的东西,例如泛型已经由Microsoft编写。
    2. 如果你的测试工作量如此之大,也许你的对象/方法做的事情太多了。
    3. 下载TestDriven.NET,就可以在Visual Studio上立即开始进行单元测试(除非你使用的是Express版本)。
    4. 只需要测试正确的结果,不必测试所有可能出错的情况:你需要等待测试失败才能这样做。
    说真的,朋友,去做吧。 :)

    1
    #1 这是要让人放心的吗??(我知道 - 选择器没有问题) - Andrew Grimm

    0
    在过去的一年里,我越来越确信TDD的好处。沿途学到的东西有: 1)依赖注入是你的朋友。我不是指控制反转容器和框架来组装插件体系结构,而是将依赖项传递到正在测试的对象的构造函数中。这将为您的代码的可测试性带来巨大回报。 2)我怀着改变信仰者的激情/狂热出发并抓住一个模拟框架,开始尽可能地使用模拟。这导致了脆弱的测试,需要大量痛苦的设置,并且只要我开始任何重构,就会崩溃。使用正确类型的测试替身。在您只需要遵守接口的情况下使用伪造品,在向正在测试的对象返回数据的情况下使用存根,在您关心交互的情况下使用模拟。 3)测试应该很小。每个测试都应该针对一个断言或交互进行测试。我试图做到这一点,而且大多数时候我都能做到。这涉及到测试代码的稳健性以及以后需要重新访问测试时测试的复杂程度。
    我在TDD中遇到的最大问题是处理来自标准机构和事实上的标准第三方实现的规范。我按照规范编写了很多非常好的单元测试,结果发现对面的实现把标准视为一个咨询文件,他们非常随意。唯一解决这个问题的办法是除了单元测试之外还要与实现一起进行测试,并根据需要重构测试和代码。真正的问题是我一直认为只要有代码和单元测试就可以了,但事实并非如此。您需要在进行单元测试时同时构建实际输出并执行功能测试。小的好处贯穿整个过程-进入用户或利益相关者手中。

    0

    作为补充,我想说一下,我已经发布了一篇博客文章,介绍了我的测试入门思路(根据这个讨论和我的研究),因为它可能对查看此线程的人有用。

    "TDD – 入门指南" - 到目前为止,我已经得到了一些很好的反馈,并且非常感谢你们提供的任何意见。

    希望这可以帮助! :)


    0

    我并不是TDD的专家,但这是我的看法:

    • 如果它完全是琐碎的(如getters/setters等),不要测试它,除非你对代码没有信心。
    • 如果它是一个相当简单但非平凡的方法,请进行测试。测试可能很容易编写。
    • 关于预期不会发生什么,我认为如果某个潜在问题是正在测试的类的责任,那么您需要测试它是否正确处理。如果不是当前类的责任,则不要测试它。

    xUnit测试框架通常是免费使用的,因此如果您是.Net开发人员,请查看NUnit,如果您是Java开发人员,请查看JUnit。


    0
    以上建议很好,如果你想要一个免费框架列表,你只需要查看维基百科上的xUnit Frameworks List。希望这能帮到你 :)

    0
    在我看来(可能因人而异):
    1- 如果你没写它,就不要测试它。如果你写了它但没有对它进行测试,那它就不存在。
    3- 众所周知,xUnit是免费且很棒的。
    2和4- 确定需要测试什么是你可以永远与自己争辩的事情之一。我尝试使用设计契约原则来画线。请查阅《面向对象软件构建》或《程序员修炼之道》以获取详细信息。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接