如何开始单元测试或TDD?

时间:2009-09-02 05:17:37

标签: unit-testing tdd

我阅读了很多帖子,说服我应该开始编写单元测试,我也开始使用依赖注入(Unity)以便更容易进行模拟,但我仍然不确定我应该在什么阶段开始写单元测试和模拟,以及如何或从哪里开始。

首选方法是在TDD方法中描述的方法之前编写单元测试吗?

单元测试是否有不同的方法或方式?

14 个答案:

答案 0 :(得分:32)

先测试/测试后:

应该注意的是,作为TDD的一部分,“先测试”与设计一样多(如果不是更多)与单元测试一样。它本身就是一种软件开发技术 - 编写测试结果可以不断改进设计。

单独注意:如果从单元测试的角度来看TDD有一个显着优势,那就是在进行TDD时编写一个错误的测试要困难得多(尽管不是不可能)。如果您事先编写测试,则始终会失败,因为执行测试所需的逻辑尚不存在。如果你之后编写测试,逻辑应该,但如果测试被错误或正在测试错误的东西,它可能会通过。

即。如果你以前写过一个不好的测试,当你期望红色时你会得到绿灯(所以你知道测试是坏的)。如果你之后写了一个不好的测试,当你期望一个绿色(没有意识到不好的测试)时,你会得到绿灯。

<强>图书

实用的单元测试书非常值得一看,Roy Osherove的“单元测试艺术”也是如此。实用主义书更侧重于您可以尝试查找错误的不同类型的测试输入,而TAOUT涵盖了更广泛的主题,如测试双打,策略,可维护性等。这两本书都很好;这取决于你想要的东西。

此外,这是一个link to a talk Roy Osherove did on unit testing。它值得一看(他记录的一些测试评论视频也是如此,因为他指出了各种问题和注意事项以及原因)。

如何开始

没有比编写代码更好的了。找一个相当简单的类,但没有引用其他内容。然后,开始编写一些测试。

总是问自己“我想尝试用这个测试来证明什么?”在你编写它之前,给它一个不错的名字(通常涉及被调用的方法,场景和预期的结果,例如在堆栈上:“Pop WhenStackIsEmpty ThrowsException”)。

想想你可以投入的所有输入,可能产生有趣结果的不同方法组合等等。

答案 1 :(得分:14)

如果您对单元测试感到好奇,最好的学习方法是尝试它。您可能会首先开始编写集成测试,但这很好。当它们看起来难以维护或编写太多工作时,请阅读更多有关哪种测试(单元,功能,集成)并尝试了解其中的差异。

如果您有兴趣从TDD开始,那么鲍勃叔叔是一个很好的资源。 Particalulary this

有关单元测试的更多信息

确保获得一致的测试结果。重复运行相同的测试应该始终如一地返回相同的结果。

测试不需要配置。

测试顺序无关紧要。这意味着部分测试运行可以正常工作。此外,如果您牢记这一设计理念,它可能有助于您的测试创建。

请记住,任何测试都优于没有测试。在编写良好的清洁单元测试时可以找到困难,这些测试可以简化创建和维护。测试框架越难,使用它就越反对。测试是你的朋友。

答案 2 :(得分:9)

在C#和visual studio中,我发现以下程序非常有用:

  1. 想想!做一个小的前期设计。您需要清楚地了解您需要哪些类以及对象应如何相互关联。只关注一个类/对象(您要实现的类/对象)和一个关系。否则你最终会有一个太重量级的设计。我常常在一张备用的纸上画出多个草图(只有几个方框和箭头)。

  2. 在生产代码中创建类并正确命名。

  3. 选择要实现的类的一种行为,并为其创建方法存根。使用visual studio创建空方法存根是件小事。

  4. 为它编写测试。因此,您需要初始化该对象,调用该方法并生成一个断言来验证结果。在最简单的情况下,断言需要生产代码中的另一个方法存根或属性。

  5. 编译并让测试运行器显示红色条!

  6. 在生产代码中对所需行为进行编码,以查看绿色条。

  7. 转到下一个行为。

  8. 对于这个程序,有两件事非常重要:

    • 你需要一个清晰的图片你想要什么以及类/对象应该是什么样子。至少花一些时间。
    • 考虑类/对象的行为。这将使测试和生产代码以行为为中心,这是一种考虑类/对象的非常自然的方法。

    先测试还是先测试?

    我发现将测试改装到现有的生产代码通常更难。在大多数情况下,当需要初始化被测对象时,这是由于与其他对象的纠缠不清。 TDD通常会避免这种情况,因为您希望尽可能少地在测试用例中初始化对象。这将导致非常松散的耦合。

    当我改进测试时,必须繁琐的工作是初始化测试对象的任务。由于纠结的依赖性,断言也可能是很多工作。为此,您需要更改生产代码并破坏依赖关系。通过正确使用依赖注入,这应该不是问题。

答案 3 :(得分:7)

是的,执行TDD的首选方式是首先编写测试(正如名称​​测试驱动开发所暗示的那样)。当你开始使用TDD时,很难知道从哪里开始编写测试,所以我建议对它采取务实态度。毕竟,我们工作中最重要的部分是提供工作代码,而不是如何制作代码。

因此,您可以从为现有代码编写测试开始。一旦你了解了单元测试的结构,哪些看起来做得不错,哪些看起来不那么神,那么你会发现更容易深入到测试优先的方法。我发现随着时间的推移,我首先在更大程度上编写测试。随着经验的增加,它变得更加自然。

答案 4 :(得分:5)

史蒂夫桑德森对TDD最佳实践有很好的写作。

http://feeds.codeville.net/~r/SteveCodeville/~3/DWmOM3O0M2s/

此外,还有很多关于做ASP.net mvc项目的教程,讨论了很多TDD原则(如果你不介意沿途学习ASP.net MVC) http://www.asp.net/learn/mvc-videos/在页面底部查找“店面”系列。

MOQ最近似乎是热门的模拟框架,你可能也想研究一下

总之,尝试编写一个测试来验证您尝试归档的内容,然后实现代码以使其正常工作。

这种模式被称为Red - Green - Refactor。还要尽力减少依赖关系,以便测试可以专注于一个组件。

就个人而言,我使用Visual Studio单元测试。我不是铁杆TDD开发人员,但我喜欢这样做:

  1. 创建一个新项目并根据系统设计定义一些基础类(这样我至少可以获得一些智能感知)
  2. 创建一个单元测试项目并开始编写单元测试以满足我正在尝试实现的功能。
  3. 让他们失败
  4. 让它们通过(实施)
  5. 重构
  6. 重复一遍,尝试使测试更严格或创建更多测试,直到我感觉它坚实。
  7. 我还觉得在现有的代码库中添加功能非常有用。如果要添加一些新功能,首先要为要添加的内容创建单元测试,单步执行代码以查看必须更改的内容,然后完成TDD过程。

答案 5 :(得分:5)

选择一个小的非关键应用程序并使用TDD实现它。起初,新的思维方式会让人觉得奇怪,但也许经过一两个星期的练习后,感觉很自然。

Here is a tutorial application(在分支“教程”中)显示要编写的测试类型。在该教程中,您编写代码以传递预定义的测试用例,以便您进入节奏,然后再编写自己的测试。 README文件包含说明。它是用Java编写的,但您可以轻松地将其调整为C#。

答案 6 :(得分:4)

我将采用TDD,测试优先开发,之前模拟和依赖注入。嗯,模拟可以帮助你更好地隔离你的单位 - 从而做更好的单元测试 - 但在我看来,模拟和DI是更先进的概念,可能会干扰只是编写测试的清晰度第一

Mocks和DI都有自己的位置;它们是您工具箱中的好工具。但它们比典型的新手测试更复杂,更先进。然而,首先编写测试就像听起来一样简单。所以它更容易接受,它本身就很强大(没有模拟和DI)。通过首先编写无模拟测试,您可以获得更早,更轻松的胜利,而不是尝试同时开始使用模拟, TDD, DI。

从测试优先开始;如果你对它很满意,当你的代码告诉你需要模拟时,那么然后就可以进行模拟。

答案 7 :(得分:3)

我曾为那些过度进行单元测试/集成测试的公司和那些做得太少的公司工作过,所以我觉得我在两者之间有很好的平衡。

我会推荐TDD - 测试驱动开发。这可确保您获得良好的覆盖率,但同时也会将注意力集中在正确的位置和问题上。

所以你为每一个新开发项目做的第一件事就是编写一个单元测试 - 即使你没有一个单独的类来测试。

考虑一下你在测试什么。现在运行测试。为什么不编译?因为你需要classA。创建类并运行测试。为什么不编译?因为它没有methodA。编写方法一并再次运行单元测试。为什么测试失败?因为methodA没有实现。实现方法A并运行测试。为什么会失败?因为methodA没有返回正确的期望值......等等

你继续像开发那样编写单元测试,然后最终测试将通过,这部分功能将完成。

答案 8 :(得分:2)

延伸史蒂夫弗里曼的答案:戴夫阿斯特尔的书名为“测试驱动开发 - 实用指南”。如果您正在编写的应用程序类型是GUI应用程序,那么这应该会有所帮助。我读过Kent Becks的书,但我无法弄清楚如何用TDD开始一个项目。 Astel的书测试 - 使用故事从头到尾测试一个完整的非平凡的GUI应用程序。它帮助我开始使用TDD,它向我展示了在何处以及如何开始。

答案 9 :(得分:2)

测试驱动的开发对于初学者来说可能会让人感到困惑,我在学习TDD时读到的很多书都会教你如何编写计算器类的单元测试但是对构建真实世界的应用程序的帮助似乎很少,如果我敢说,那就更加以数据为中心了。对我来说,突破是当我理解什么是行为驱动开发或BDD以及如何从外部开始进行测试时。现在我可以建议您专注于您的应用程序行为并编写单元测试来验证它。 TDD和BDD之间存在很多争论,但我认为在每个级别上编写良好的自动化测试都会增加价值并编写它们,我们需要关注行为。

Hadi Hariri在这里有一篇很棒的帖子 http://hadihariri.com/2012/04/11/what-bdd-has-taught-me/

我还写了一些关于这个主题的文章,我认为这将有助于理解与TDD相关的所有概念

http://codecooked.com/introduction-to-unit-testing-and-test-driven-development/

http://codecooked.com/different-types-of-tests-and-which-ones-to-use/

答案 10 :(得分:1)

阅读Pragmatic Unit Testing in C# with NUnit。它提供了有关开始编写睾丸和构造代码的全面信息,以使其更适合单元测试。

答案 11 :(得分:1)

如果您之前没有编写单元测试,那么只需选择一些类并开始编写单元测试,然后继续开发更多的单元测试。

当你获得经验时,你可以通过使用Unity框架开始模拟数据库,但是,我建议在进行此跳跃之前先简单地开始并获得经验。

一旦您对如何编写单元测试感到满意,那么您可以尝试进行TDD。

答案 12 :(得分:0)

我更喜欢KentBeck的方法,该方法在“按示例进行测试驱动开发 - Kent Beck”一书中得到了很好的解释。

从您的问题我可以推断您对测试框架的工作不确定 - 选择正确的测试框架工作对于TDD或编写单元测试(一般而言)非常重要。

TDD唯一的实际问题是“重构”(我们需要重构测试代码)需要花费大量时间。

答案 13 :(得分:0)

我认为Dave Astels的书仍然是最好的介绍之一。它适用于Java,但您应该能够翻译。