代码之家  ›  专栏  ›  技术社区  ›  Thorsten79

单元测试文档[关闭]

  •  11
  • Thorsten79  · 技术社区  · 15 年前

    我想从那些记录单元测试的人那里知道他们是如何记录它的。我理解,大多数TDD追随者都声称“代码会说话”,因此测试文档不是很重要,因为代码应该是自描述性的。很公平,但我想知道 怎样 记录单元测试,而不是 是否 把它们记录下来。

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

    那么在测试文档中什么是重要的呢?什么时候测试方法名称描述不够充分,以致于文档是合理的?

    6 回复  |  直到 8 年前
        1
  •  11
  •   OregonGhost    15 年前

    应托尔斯滕79的要求,我将详细阐述我的意见作为回答。我最初的评论是:

    不幸的是,“密码说话” 完全错误,因为 非开发人员无法读取代码, 虽然他至少能部分阅读 了解生成的 文件,这样他就可以 知道什么是测试。这是 特别重要的是 客户完全理解 域,无法读取代码,以及 当这个单位 测试还测试硬件,如 嵌入式世界,因为你测试 可以看到的东西。

    当你做单元测试时,你必须知道你是为你自己(或你的同事)写的,还是为其他人写的。很多时候,你应该写代码 给你的读者 而不是为了你的方便。

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

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

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

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

    在这个上下文中,正确的意思是:写出非开发人员可以理解的清晰的语言。你可以保持技术性,但不要写只有你能理解的东西。当然,对于任何其他注释和代码,后者也很重要。

    独立于我们的具体情况,我认为这就是我在单元测试中一直想要的,即使它们是纯软件。客户可以忽略他不关心的单元测试,比如基本功能测试。但是只要有医生就不会有伤害。

    正如我在对另一个答案的评论中所写的那样:另外,如果您(或者您的老板、同事、或者测试部门)想要检查哪些测试以及它们做了什么,那么生成的文档也是一个很好的起点,因为您可以浏览它而不必深入代码。

        2
  •  4
  •   b.roth    15 年前

    在测试代码本身中:

    • 方法级注释解释 测试/覆盖的内容。

    • 在类级别上,指示正在测试的实际类的注释(实际上可以从测试类名称中推断出来,这样实际上比方法级别上的注释更不重要)。

    有测试覆盖率报告

    • Cobertura . 这也是文档,因为它指出了您的测试覆盖了什么,而不是什么。
        3
  •  3
  •   Finglas    15 年前

    评论复杂的测试或场景(如果需要),但是 有利于可读测试 首先。

    另一方面,我试着让我的测试自己说出来。换言之:

    [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");
    }
    

    如果我要看这个测试,我会看到它是用过的人 PersonTest.cs 作为一个线索;)那么如果有任何东西损坏,它将发生在 SayHello 方法。断言消息也很有用,不仅用于读取测试,而且在运行测试时,在GUI中更容易看到它们。

    跟随 AAA 排列、动作和断言的风格使得测试基本上是文档本身。如果这个测试更复杂,您可以在测试函数的上方添加注释,解释发生了什么。一如既往,您应该确保这些都是最新的。

    作为补充说明,对测试名称使用下划线符号使它们更易于阅读,将其与以下内容进行比较:

    public void PersonShouldSayHello()
    

    对于较长的方法名称,这会使阅读测试更加困难。尽管这一点通常是主观的。

        4
  •  1
  •   Lieven Keersmaekers    15 年前

    当我回到一个旧的测试中,却不马上理解它的时候

    1. 如果可能,我重构
    2. 或者写一篇能让我马上理解的评论

    当你写测试用例的时候,它和你写代码的时候是一样的,每件事对你来说都是非常清楚的。这使得你很难想象你应该写什么来让代码更清晰。

    注意这个 不代表我从不写评论 . 在很多情况下,当我知道我将很难弄清楚一段特定的代码在做什么时。

    在这种情况下,我通常从第一点开始……

        5
  •  1
  •   philant    15 年前

    将单元测试改进为可执行规范是 Behaviour-Driven Development :bdd是tdd的一个演变,其中单元测试使用 Ubiquitous Language (基于业务域并由开发人员和利益相关者共享的语言)和表达性名称( 测试无法创建重复项 )描述代码应该做什么。一些BDD框架把这个想法推进了很远,并且显示了用几乎自然语言编写的可执行文件,因为 example .

        6
  •  0
  •   Guido    8 年前

    我会反对任何 详细的 与代码分开的文档。为什么?因为当你需要它的时候,它很可能 非常 过时的。详细文档的最佳位置是代码本身(包括注释)。顺便说一句,关于一个特定的单元测试,你需要说什么 非常详细的文件。

    关于如何实现良好的自我记录测试的几点建议:

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

    • 将常见逻辑提取到具有描述性名称的set-up/teardown或helper方法中。

    • 尽可能使用实际数据中的样本作为输入值。这比空白对象或组成的JSON提供了更多的信息。
    • 使用具有描述性名称的变量。
    • 想想你的未来,你/队友,如果你什么都不记得的话,当测试失败的时候,你想知道更多的信息吗?写下来作为评论。

    补充其他答案:

    • 如果您的客户/产品所有者/老板对应该测试的内容有一个非常好的想法,并且希望能够提供帮助,那就太好了,但是单元测试是 最好的地方。 您应该为此使用验收测试 .

    • 单元测试应该覆盖特定的代码单元(类/模块中的方法/函数),如果您覆盖更多的基础,它们很快就会变成集成测试,这也是很好的,也很需要的,但是如果您不具体地将它们分开,人们就会把它们弄糊涂,您会失去单元测试的一些好处。例如,当单元测试失败时,您应该得到即时的错误检测(特别是如果您遵循上面的命名约定)。当一个集成测试失败时,您知道有一个问题,并且知道它的一些影响,但是您可能需要调试,有时需要很长时间,才能找到它是什么。

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

    • 有很好的验收/行为测试框架(fitnesse、robot、selenium、cumber等),可以帮助企业/领域人员不仅阅读测试,还可以自己编写测试。当然,他们需要编码人员的帮助才能让他们工作(特别是在开始工作的时候),但是他们能够做到这一点,而且他们不需要知道任何关于模块或函数类的信息。