如何编写好的单元测试?

时间:2009-10-08 22:52:46

标签: c++ unit-testing tdd

有人可以建议书籍或材料来学习单元测试吗?

有些人认为没有单元测试的代码是遗留代码。如今,测试驱动开发是一种轻松管理大型软件项目的方法。我非常喜欢C ++,我没有接受任何正规教育就自己学习。我之前从未考虑过单元测试,所以感到被遗忘了。我认为单元测试很重要,从长远来看会有所帮助。我将不胜感激这个主题的任何帮助。

我主要关注的是:

  1. 什么是单元测试?它是一个应该分析的测试用例的综合列表吗?所以让我们说一下我有一个名为“复数”的类,其中包含一些方法(让我们说找到共轭,一个重载的赋值运算符和一个重载的乘法运算符。这类的典型测试用例应该是什么?有什么方法吗?选择测试用例?

  2. 是否有任何框架可以为我创建单元测试,或者我必须编写自己的类进行测试?我在Visual Studio 2008中看到了一个“测试”选项,但从未使它工作。

  3. 单元测试的标准是什么?是否应对班级中的每个功能进行单元测试?为每个班级进行单元测试是否有意义?

10 个答案:

答案 0 :(得分:22)

一个重点(我在开始时没有意识到)是单元测试是一种可以单独使用的测试技术,无需应用完整的测试驱动方法。

例如,您希望通过向问题区域添加单元测试来改进遗留应用程序,或者希望在现有应用程序中查找错误。现在,您编写单元测试以公开问题代码,然后进行修复。这些是半测试驱动的,但可以完全适合您当前的(非TDD)开发过程。

我发现有用的两本书是:

Test Driven Development in Microsoft .NET

继承了Kent Becks的原创TDD书之后,非常亲眼目睹了测试驱动开发。

Pragmatic Unit Testing with C# and nUnit

直接指出单元测试是什么,以及如何应用它。

回应你的观点:

  1. 单元测试,实际上是一个类中的单个方法,它只包含足够的代码来测试应用程序的一个方面/行为。因此,您通常会进行许多非常简单的单元测试,每个单元测试都会测试一小部分应用程序代码。例如,在nUnit中,您将创建一个包含任意数量测试方法的TestFixture类。关键点在于测试“测试代码的单位”,即尽可能小的(合理的)单位。您不会测试您使用的基础API,只测试您编写的代码。

  2. 有些框架可以承担创建测试类的一些繁琐的工作,但我不建议这样做。要创建实际为重构提供安全网的有用单元测试,除了让开发人员考虑如何以及如何测试其代码之外别无选择。如果您开始依赖于生成单元测试,那么很容易将它们视为必须完成的另一项任务。如果你发现自己处于这种情况,你就完全错了。

  3. 没有关于每个类,每个方法等多少单元测试的简单规则。您需要查看应用程序代码并对复杂性存在的位置进行有根据的评估,并为这些区域编写更多测试。大多数人开始只测试公共方法,因为这些方法通常会运用其余的私有方法。然而,情况并非总是如此,有时需要测试私有方法。

  4. 简而言之,即使是经验丰富的单元测试人员也可以通过编写明显的单元测试来开始,然后在编写明显的测试后,寻找更加细微的测试。他们不希望事先得到每个测试,而是在他们想到的时候添加它们。

答案 1 :(得分:7)

虽然您已经接受了问题的答案,但我还是想推荐一些尚未提及的其他书籍:

  • 有效地使用遗留代码 - Michael Feathers - 据我所知,这是唯一能够充分解决将不是为可测试性而设计的现有代码转换为可测试代码的主题的书。作为更多的参考手册,它分为三个部分:工具和技术概述,遗留代码中常见路障的一系列主题指南,本书其余部分引用的一组特定依赖性破坏技术
  • 敏捷原则,模式和实践 - Robert C. Martin - Java中的例子,C#中有一个例子的续集。两者都很容易适应C ++
  • 清洁代码:敏捷软件工艺手册 - 罗伯特C.马丁 - 马丁将其描述为他的APPP书籍的前传,我同意。本书为专业和自律提供了理由,这是任何认真的软件开发人员的两个基本素质。

罗伯特(鲍勃叔叔)马丁的这两本书所涵盖的内容远远超过了单元测试,但是他们将单元测试的代码质量和生产力提升到了有利位置。我发现自己经常提到这三本书。

答案 2 :(得分:2)

  1. 使用测试驱动设计,您通常希望首先编写测试。它们应涵盖您实际使用/将要使用的操作。即除非它们是客户端代码完成工作所必需的,否则它们不应该存在。选择测试用例是一件艺术。有一些显而易见的事情,比如测试边界条件,但最后,没有人发现一种真正可靠,系统的方法来确保测试(单位或其他方面)涵盖所有重要的条件。

  2. 是的,有框架。一些最着名的是:
    Boost Unit Test Framework
    CPPUNit

    CPPUnit是JUnit的一个端口,所以那些以前使用过JUnit的人可能会觉得它很舒服。否则,我倾向于推荐Boost - 他们也有一个Test Library来帮助编写单独的测试 - 而不是一个方便的添加。

  3. 单元测试应该足以确保代码有效。如果(例如)您有一个内部使用的私有函数,通常不需要直接测试它。相反,您测试提供公共接口的任何内容。只要这种方法能够正常运行,外界的工作就无法完成它的工作。当然,在某些情况下,更容易来测试小块,当它是,这是完全合法的 - 但最终你关心的是可见界面,而不是内部。当然应该运用整个外部接口,并且通常选择测试用例来遍历代码。同样,单元测试与其他类型的测试没有什么大不相同。它主要是采用常规测试技术的一种更系统的方式。

答案 3 :(得分:2)

在.NET中,我强烈推荐Roy Osherove的“单元测试艺术”,它非常全面且充满了很好的建议。

答案 4 :(得分:2)

  

如今,测试驱动开发是   管理大软件的方法   项目很轻松。

这是因为TDD允许您确保在每次更改之后,在更改之前工作的所有内容仍然有效,如果不能,则可以让您更准确地查明已损坏的内容。 (见最后)

  

什么是单元测试?是一个   全面的测试用例列表   应该分析一下吗?

单元测试是一段代码,它要求代码的“单元”执行操作,然后验证操作是否确实执行,结果是否符合预期。如果结果不正确,则会引发/记录错误。

  

所以,让我们说我有一个叫做的课   “复数”与一些方法   它(让我们说找到共轭,一个   重载赋值运算符和   重载乘法运算符。   什么应该是典型的测试用例   这样的课程?有没有任何方法论   选择测试用例?

理想情况下,您将测试所有代码。

  • 创建实例时 class,它是用正确的创建的 默认值

  • 当你要求它找到时 结合,它确实找到了正确的 那些(也测试边界情况,如 共轭为零)

  • 分配值时,值为 分配并正确显示

  • 将复数乘以a时 值,它正确相乘

  

他们的任何框架都可以   为我或我必须创建单元测试   写我自己的课程进行测试?

请参阅CppUnit

  

我在Visual中看到了“Test”选项   Studio 2008,但从未让它发挥作用。

不确定。我没有使用VS 2008,但它可能仅适用于.NET。

  

单元测试的标准是什么?   是否应该对每个进行单元测试   和班级中的每个功能?可以   有意义的是为每个人进行单元测试   每个班级?

是的,确实如此。虽然这是一个非常多的代码编写(并保持每次更改)价格是值得为大型项目支付:它保证您对代码库的更改执行您希望他们的其他内容

此外,当您进行更改时,您需要更新该更改的单元测试(以便它们再次通过)。

在TDD中,您首先要确定您希望代码执行的操作(例如,您的复数类),然后编写验证这些操作的测试,然后编写类以便测试编译并正确执行(仅此而已)。

这可确保您尽可能编写最小代码(并且不会使复杂类的设计过于复杂),并确保您的代码能够完成它所做的工作。在编写代码的最后,您可以测试它的功能并确保其正确性。

您还有一个使用您可以随时访问的代码的示例。

有关进一步阅读/文档,请查看单元测试和TDD中使用的“依赖注入”和方法存根。

答案 5 :(得分:1)

我无法回答您对Visual Studio 2008的问题,但我知道Netbeans有一些集成工具供您使用。

  1. 代码覆盖率2允许您查看已检查的路径,以及单元测试实际覆盖了多少代码。
  2. 它支持内置的单元测试。
  3. 就测试质量而言,我从Andrew Hunt和David Thomas的“Pragmatic Unit Testing in Java with JUnit”借了一点:

    单元测试应检查 BICEP B oundary,负面关系, C ross-checking, E rror条件, P < /强> erformance。

    测试的质量也由 A-TRIP 确定: A utomatic, T horough, R 可依赖,独立, P 专业

答案 6 :(得分:1)

单元测试只是一种运用给定代码体的方法,以确保一组已定义的条件导致预期的out出现。史蒂文指出,这些“练习”应该检查一系列标准(“BICEP”)。是的,理想情况下,您应该测试所有类和这些类中的所有方法,尽管总有一些判断空间:测试本身不应该是目的,而应该支持更广泛的项目目标。

好的,所以...理论很好但是为了真正理解单元测试,我的建议是将相应的工具整合在一起并开始使用。像编程中的大多数东西一样,如果你有合适的工具,那么通过这样做很容易学习。

首先,选择NUnit的副本。它免费,易于安装且易于使用。如果您需要一些文档,请查看Pragmatic Unit Testing in C# with NUnit.

接下来,转到http://www.testdriven.net/并获取TestDriven.net的副本。它安装在Visual Studio 2008中,允许您右键单击访问所有测试工具,包括对文件,目录或项目运行NUnit测试的能力(通常,测试是在单独的项目中编写的)。您还可以使用调试运行测试,或者最酷的是,对NCover的副本运行所有测试。 NCover将向您显示完全正在执行的代码,以便您可以找出改善测试覆盖率所需的位置。 TestDriven.net的专业许可费用为170美元,但如果你像我一样,它很快就会成为你工具箱中不可或缺的工具。无论如何,我发现这是一项很好的专业投资。

祝你好运!

答案 7 :(得分:0)

这里有一些关于什么时候不编写单元测试(即什么时候它可行,甚至更喜欢跳过单元测试):Should one test internal implementation, or only test public behaviour?

简短的回答是:

  • 当您可以自动化集成测试时(因为自动化测试很重要,但这些测试不一定是单元测试)
  • 运行集成测试套件的成本很低(如果运行需要两天,或者你不能让每个开发人员都能访问集成测试设备,那就不好了)
  • 在集成测试之前没有必要找到错误(部分取决于组件是单独开发还是逐步开发)

答案 8 :(得分:0)

购买“xUnit测试模式:重构测试代码”一书。它非常优秀。它确实涵盖了高级别战略决策以及低级别测试模式。

答案 9 :(得分:0)

  

如今,测试驱动开发是一种轻松管理大型软件项目的方法。

TDD建立在单元测试的基础上,但它们是不同的。您不需要使用TDD来使用单元测试。我个人的偏好是首先编写测试,但我不觉得我做了整个TDD的事情。

  

什么是单元测试?

单元测试是一些测试一个单元行为的代码。一个单位的定义方式因人而异。但总的来说,它们是:

  1. 快速投放
  2. 彼此独立
  3. 仅测试代码库的一小部分(单位;)。
  4. 二进制结果 - 即通过或失败。
  5. 应该只测试一个单元的结果(每个结果创建一个不同的单元测试)
  6. 重复
  7.   

    他们的任何框架都可以创建单元测试

    写测试 - 是的,但我从未见过有人对他们说过任何好话。
    为了帮助你写作&amp;运行测试,whole bunch

      

    是否应对班级中的每个功能进行单元测试?

    你有几个不同的阵营 - 100%的人会说是的。必须测试每种方法,你应该有100%code coverage。另一个极端是单元测试应该只覆盖你甚至遇到错误或你希望发现错误的区域。中间地带(以及我采取的立场)是对所有不“太简单而无法破坏”的东西进行单元测试。 Setters / getters以及任何只调用其他方法的东西。我的目标是拥有80%的代码覆盖率和低CRAP因子(所以我很顽皮的机会很少,并决定不测试某些东西,因为它“太复杂而无法测试”。

    帮助我“获得”单元测试的书JUnit in Action。对不起,我在C ++世界中做的不多,所以我不能建议基于C ++的替代方案。