单元测试文档

时间:2010-02-04 09:16:05

标签: unit-testing language-agnostic documentation

我想知道那些记录单元测试如何记录它的人。据我所知,大多数TDD粉丝声称“代码说话”,因此测试文档不是很重要,因为代码应该是自我描述的。很公平,但我想知道如何来记录单元测试,而不是是否来记录它们。

我作为开发人员的经历告诉我,理解旧代码(包括单元测试)很困难。

那么在测试文档中重要的是什么?何时测试方法名称的描述性不够,以便证明文档合理?

6 个答案:

答案 0 :(得分:11)

根据Thorsten79的要求,我将详细阐述我的评论作为答案。我原来的评论是:

  不幸的是,“代码说话”   完全错了,因为一个   非开发人员无法读取代码,   虽然他至少可以部分阅读   并了解生成   文档,这样他就可以   知道测试测试的内容。这是   特别重要的是   客户完全理解   域,只是无法读取代码,和   在单位时变得更加重要   测试也测试硬件,如在   嵌入式世界,因为那时你测试   可以看到的东西。

当你进行单元测试时,你必须知道你是为你(或同事)写的,还是你也是为别人写的。很多时候,您应该为您的读者编写代码,而不是为了您的方便。

在我公司的混合硬件/软件开发中,客户知道他们想要什么。如果他们的现场设备在接收某个总线命令时必须进行复位,则必须有一个单元测试发送该命令并检查设备是否被重置。我们现在正在这里使用NUnit作为单元测试框架,以及一些可以发送和接收命令(甚至按下按钮)的自定义软件和硬件。这很棒,因为唯一的选择就是手动完成所有操作。

客户绝对想知道哪些测试,他甚至想自己运行测试。如果没有正确记录测试,他不知道测试做了什么,也无法检查他认为他需要的所有测试是否存在,并且在运行测试时,他不知道它会做什么。 因为他无法读取代码。他比我们的开发人员更了解所使用的总线系统,但他们无法读取代码。如果测试失败,他不知道为什么甚至不能说他认为测试应该做什么。这不是一件好事。

正确记录单元测试后,我们

  • 开发人员的代码文档
  • 客户的测试文档,可用于证明设备可以执行的操作,即客户订购的内容
  • 能够以任何格式生成文档,甚至可以传递给其他相关方,例如制造商

在此上下文中正确表示:编写非开发人员可以理解的清晰语言。你可以保持技术,但不要只写你能理解的东西。对于任何其他评论和任何代码,后者当然也很重要。

独立于我们的确切情况,我认为这是我在单元测试中一直想要的,即使它们是纯软件。客户可以忽略他不关心的单元测试,例如基本功能测试。但只是拥有那里的文档永远不会受到伤害。

正如我在评论中写到另一个答案:此外,如果您(或您的老板,同事或测试部门)想要检查哪些测试是,那么生成的文档也是一个很好的起点在那里和他们做了什么,因为你可以浏览它而不需要挖掘代码。

答案 1 :(得分:4)

在测试代码中:

  • 使用方法级别的注释进行解释 测试/覆盖测试的内容。

  • 在类级别,一个注释指示正在测试的实际类(实际上可以从测试类名称中推断出来,因此实际上不如方法级别的注释重要)。

使用测试覆盖率报告

  • 例如Cobertura。这也是文档,因为它表明了您的测试覆盖的内容以及它们不是什么。

答案 2 :(得分:3)

首先评论复杂测试或方案(如果需要,但支持可读测试)。

另一方面,我尝试让我的测试说明一切。换句话说:

[Test]
public void person_should_say_hello() {
     // Arrange.
     var person = new Person();
     // Act.
     string result = person.SayHello();
     // Assert.
    Assert.AreEqual("Hello", result, "Person did not say hello");
}

如果我要查看这个测试,我会看到它使用Person(虽然它会在PersonTest.cs中作为线索;))然后如果有任何中断,它将发生在SayHello方法。断言消息也很有用,不仅用于读取测试,而且在运行测试时,更容易在GUI中看到它们。

遵循AAA样式的Arrange,Act和Assert使测试基本上记录了自己。如果这个测试更复杂,你可以在测试函数上面添加注释来解释发生了什么。与往常一样,您应该确保这些保持最新。

作为旁注,对测试名称使用下划线表示法使它们更易于阅读,将其与以下内容进行比较:

public void PersonShouldSayHello()

对于长方法名称,可以使阅读测试更加困难。虽然这一点通常是主观的。

答案 3 :(得分:1)

当我回到旧测试并且不能立即理解时

  1. 如果可能,我重构
  2. 或写下那些让我立刻理解的评论
  3. 当您编写测试用例时,它与您编写代码时的情况相同,每个人都非常清楚。这使得很难想象你应该写什么来使代码更清晰。

    请注意,此并不代表我从不撰写任何评论。当我知道我将很难弄清楚特定代码片段的作用时,仍有很多情况。

    在这些情况下,我通常从第1点开始......

答案 4 :(得分:1)

将单元测试改进为可执行规范是Behaviour-Driven Development的要点:BDD是TDD的演变,其中单元测试使用Ubiquitous Language(一种基于业务领域并由开发人员共享的语言)和利益相关者)和富有表现力的名称( testCannotCreateDuplicateEntry )来描述代码应该做什么。一些BDD框架推动了这个想法,并用example显示用几乎自然语言编写的可执行文件。

答案 5 :(得分:0)

我建议不要与代码分开的任何详细的文档。为什么?因为无论什么时候需要它,它很可能非常过时。详细文档的最佳位置是代码本身(包括注释)。顺便说一下,关于特定单元测试所需的任何内容都是非常详细的文档。

关于如何实现良好的自我记录测试的一些指示:

  • 按照标准方式编写所有测试,例如AAA pattern。使用空行分隔每个部分。这使得读者更容易识别重要的位。
  • 您应该在每个测试名称中包括:正在测试的内容,测试中的情况以及预期的行为。例如:test__getAccountBalance__NullAccount__raisesNullArgumentException()

  • 将常用逻辑提取到具有描述性名称的设置/拆卸或辅助方法中。

  • 尽可能使用实际数据中的样本作为输入值。这比空白对象或组成JSON更有用。
  • 使用具有描述性名称的变量。
  • 想想你的未来你/队友,如果你没有想到这一点,你想在测试失败时获得任何其他信息吗?把它写成评论。

并补充其他答案所说的内容:

  • 如果您的客户/产品负责人/老板非常了解应该测试什么并且渴望提供帮助,那就太棒了,但是单元测试不是不是最好的地方它。 您应该使用验收测试

  • 单元测试应该涵盖特定的代码单元(类/模块中的方法/功能),如果你覆盖更多的地面,它们将很快变成集成测试,这很好并且也需要,但如果你不需要将它们分开,人们会让他们感到困惑,你将失去单元测试的一些好处。例如,当单元测试失败时,您应该立即检测到错误(特别是如果您遵循上面的命名约定)。当集成测试失败时,您知道存在问题,并且您知道它的一些影响,但您可能需要调试(有时很长一段时间)来查找它是什么。

  • 如果需要,可以使用单元测试框架进行集成测试,但是您应该知道自己没有进行单元测试,并且应该将它们保存在单独的文件/目录中。

  • 有很好的接受/行为测试框架(FitNesse,Robot,Selenium,Cucumber等)可以帮助业务/域名人员不仅阅读,还可以自己编写测试。当然,他们需要编码员的帮助才能让他们工作(特别是在开始时),但是他们能够做到这一点,而且他们不需要了解你的模块或功能类别。

    < / LI>
相关问题