关于单元测试:从TDD开始-挑战? 解决方案? 建议?

关于单元测试:从TDD开始-挑战? 解决方案? 建议?

Beginning TDD - Challenges? Solutions? Recommendations?

好的,我知道已经开始使用TDD了。.但是,我想我还是知道一般的共识是这样做,但是,我似乎在进入游戏时遇到以下问题:

  • 在处理集合时,即使基于仿制药等我们"知道"其正常工作的情况下,是否仍会测试明显的添加/删除/插入是否成功?
  • 有些测试似乎要花很长时间才能实现。例如,在处理字符串输出时,是否有"更好"的方式来进行这种处理? (例如,在解析之前测试对象模型,将解析分解为小操作并在其中进行测试)在我看来,您应该始终测试"最终结果",但这可能千差万别,并且设置起来很繁琐。
  • 我没有可用的测试框架(工作不会花钱),所以我可以"练习"更多。是否有任何可免费用于商业用途的优质产品? (目前我正在使用良好的'ol Debug.Assert :)
  • 可能是最大的。有时我不知道不会发生什么。我的意思是,您得到了批准,但是我始终担心我可能会错过一项测试。代码,或者保留原状并等待所有失败(这会花费更多)。

因此,基本上,我在这里寻找的不是"随便做",而是"我这样做了,遇到了问题,并通过此方法解决了"。


首先,当您第一次开始尝试以编码风格使用TDD时,感到沮丧是正常的。只是不要灰心和戒烟,您需要花一些时间。这是我们思考如何解决代码问题的主要模式转变。我喜欢这样想,就像我们从程序编程转向面向对象的编程一样。

其次,我认为测试驱动开发首先是一项设计活动,该活动通过创建一个测试来充实组件的设计,该测试首先描述将要公开的API以及您将如何使用它的功能。该测试将帮助塑造和塑造被测系统,直到您能够封装足够的功能来满足您要执行的任何任务。

考虑到以上段落,让我们看一下您的问题:

  • 如果我在测试中的系统中使用集合,那么我将设置一个期望值,以确保调用该代码以插入该项目,然后断言集合的计数。我不必在内部列表上测试Add方法。我只是确保在调用添加项的方法时调用了它。为此,我将测试框架添加到了模拟框架中。
  • 测试字符串作为输出可能很乏味。您无法解释所有结果。您只能根据被测系统的功能来测试期望的结??果。您应该始终将测试分解为要测试的最小元素。这意味着您将进行很多测试,但是测试又小又快,仅测试了应该进行的测试,没有别的。
  • 有很多开源测试框架可供选择。我不会争论哪个是最好的。只要找到您喜欢的一个并开始使用它即可。

    • 单位
    • 单位
    • 单位
  • 您所能做的就是设置测试以说明您要发生的情况。如果出现了在您的功能中引入错误的方案,那么至少您需要对该功能进行测试,以将该方案添加到测试中,然后更改您的功能,直到测试通过。找到我们可能错过测试的地方的一种方法是使用代码覆盖率。
  • 我在第一个问题的答案中向您介绍了嘲讽术语。当您将模拟引入到您的TDD军械库中时,它极大地简化了测试,从而使那些不属于被测系统的零件抽象出来。以下是有关模拟框架的一些资源:

    • Moq:开源
    • RhinoMocks:开源
    • TypeMock:商业产品
    • NSubstitute:开源

    除了阅读有关过程的信息外,帮助使用TDD的一种方法是观察人们的行为。我建议您在DNRTV上观看JP Boodhoo的屏幕广播。检查这些:

    • Jean Paul Boodhoo谈测试驱动开发第1部分
    • Jean Paul Boodhoo谈测试驱动开发第2部分
    • Jean Paul Boodhoo谈神秘的设计模式第1部分
    • Jean Paul Boodhoo谈解神秘的设计模式第2部分
    • Jean Paul Boodhoo谈解神秘的设计模式第3部分
    • Jean Paul Boodhoo谈解神秘的设计模式第4部分
    • Jean Paul Boodhoo讲解神秘的设计模式第5部分

    好的,这些将帮助您了解如何使用我介绍的术语。它还将介绍另一个称为Resharper的工具,以及该工具如何促进TDD流程。在进行TDD时,我对这个工具的推荐不够。似乎您正在学习该过程,而您只是发现使用其他工具已经解决的一些问题。

    如果不通过添加肯特·贝克(Kent Beck)的新系列《实用程序员的测试驱动开发》来更新这一点,我想我会对社区造成不公正。


    根据我自己的经验:

  • 仅测试您自己的代码,而不测试基础框架的代码。因此,如果您使用的是通用列表,则无需测试添加,删除等。

  • 没有2.看那边!猴子!

  • NUnit是必经之路。

  • 您绝对无法测试所有结果。我测试了我期望发生的事情,然后测试了一些我希望得到异常或无效响应的极端情况。如果由于忘记测试而导致错误出现,那么您应该做的第一件事(在尝试修复错误之前)是编写测试以证明该错误存在。


  • 我发现轻松记住TDD本质的三张索引卡中说明的原理是一个很好的指南。

    无论如何,回答您的问题

  • 除非您编写了它,否则您不必测试您"知道"的东西就会起作用。 你没有写泛型,微软是;)
  • 如果您需要为测试做很多事情,那么您的对象/方法也可能做得太多。
  • 下载TestDriven.NET以立即在Visual Studio上开始单元测试(除非是Express版)
  • 只需测试将要发生的正确事情即可。 您无需测试所有可能出错的地方:您必须等待测试失败。
  • 老兄,认真地做吧。 :)


    我认为,TDD最重要的事情(实际上是,以某种递归的方式带来的巨大成果之一)是对依赖关系的成功管理。您必须确保模块进行了隔离测试,而无需进行详尽的设置。例如,如果您要测试最终发送电子邮件的组件,请使电子邮件发送者具有依赖性,以便您可以在测试中对其进行模拟。
    这引出第二点-模拟是您的朋友。熟悉模拟框架及其推动的测试风格(行为,而不是基于传统的状态),以及它们鼓励的设计选择("告诉,不要问"原理)。


    我对此的看法如下:

    • +1表示不测试框架代码,但您可能仍需要测试从框架类派生的类。
    • 如果某些类/方法难以测试,则可能强烈表明设计方面存在问题。我尝试遵循" 1类-1责任,1方法-1行动"的原则。这样,您可以通过较小的部分来简化复杂方法的测试。
    • 对于xUnit +1。对于Java,您还可以考虑使用TestNG。
    • TDD不是单个事件,而是一个过程。因此,不要从一开始就设想所有事情,但是一旦发现,请确保测试中实际上涵盖了代码中发现的每个错误。

    除此之外,我想我会说我在博客上发表了有关测试入门的想法(在此讨论和我自己的研究之后),因为它可能对查看此主题的人们有用。

    " TDD –测试驱动开发入门" –到目前为止,我收到了很多反馈,非常感谢你们提供的更多信息。

    我希望这有帮助! :)


    在过去的一年中,我越来越相信TDD的好处。
    我从中学到的东西:
    1)依赖注入是您的朋友。我不是在谈论控制容器和框架的反转来组装插件架构,只是将依赖项传递到被测对象的构造函数中。这样可以在代码的可测试性方面获得可观的回报。
    2)我以对转换的热情/热情着手,并抓住了一个模拟框架,并着力于尽可能使用模拟。这导致了脆弱的测试,需要进行大量痛苦的设置,并且在我开始进行任何重构时都将失败。使用正确的测试类型两倍。伪造您仅需使用接口的地方,存根将数据反馈给被测对象,仅在您关心交互的地方进行模拟。
    3)测试应小。旨在在每个测试中测试一个断言或交互。我尝试这样做,而且大多数时候我都在那里。这与测试代码的健壮性有关,也与测试的复杂性有关(当您以后需要重新访问它时)。

    我对TDD遇到的最大问题是使用标准组织的规范以及该标准的第三方实现,即事实上的标准。我对规范的字母进行了很多非常好的单元测试编码,只是发现在栅栏另一侧的实现将标准视为咨询文档。他们玩起来很放松。解决此问题的唯一方法是对实现以及单元测试进行测试,并在必要时重构测试和代码。真正的问题是我坚信,只要我拥有代码和单元测试,一切都很好。不是这样您需要在进行单元测试的同时构建实际的输出并执行功能测试。在整个过程中,一小部分收益-一直到用户或利益相关者手中。


    保持测试简短,"原子"。在每次测试中测试最小的假设。使每个TestMethod独立,对于集成测试,我什至为每个方法创建一个新的数据库。如果您需要为每个测试构建一些数据,请使用"初始化"方法。使用模拟将测试类与依赖项隔离开。

    我一直认为"为了证明在所有情况下都行得通,我需要写的最少代码量是多少?"


    我认为(您的里程可能会有所不同):

    1-如果您没有写它,请不要对其进行测试。如果您编写它并且没有测试,那么它就不存在。

    3-众所周知,xUnit既免费又很棒。

    2&4-确定要测试的内容是您可以永远与自己争论的事情之一。我尝试使用按合同设计的原则来划清界限。查看"面向对象的软件构造"或"实用编程器"以获取有关其详细信息。


    上面的建议是很好的,并且如果您想要一个免费框架列表,那么您看起来就不会比Wikipedia上的xUnit Frameworks List更远。希望这可以帮助 :)


    无论如何,我都不是TDD的专家,但是我的观点是:

    • 如果它是完全琐碎的(getters / setters等),请不要对其进行测试,除非您出于某种原因对代码没有信心。
    • 如果这是一种非常简单但又很简单的方法,请对其进行测试。无论如何,该测试可能很容易编写。
    • 当涉及到预期不会发生的事情时,我要说的是,如果某个潜在问题是您正在测试的类的责任,那么您需要测试它是否能够正确处理。如果不是当前班级的责任,请不要对其进行测试。

    xUnit测试框架通常是免费使用的,因此,如果您是.Net的人,请签出NUnit,如果您是Java,请签出JUnit。


    推荐阅读