7

在软件开发过程中,代码库中可能存在已知问题。如果测试写得好,这些错误将导致回归/单元测试失败。

我们的团队一直在争论如何管理失败的测试:

  1. 使用 REVISIT 或 TODO 注释注释掉失败的测试用例。

    • 优点:我们将始终知道何时引入了缺陷,而不是我们已经知道的缺陷。
    • 缺点:可能会忘记重新访问已注释掉的测试用例,这意味着缺陷可能会从裂缝中溜走。
  2. 让测试用例失败。

    • 优点:不会忘记修复缺陷,因为脚本失败会不断提醒您存在缺陷。
    • 缺点:由于故障噪声,难以检测何时引入了新缺陷。

我想探讨一下这方面的最佳实践。就个人而言,我认为三态解决方案是确定脚本是否通过的最佳解决方案。例如,当您运行脚本时,您可能会看到以下内容:

  • 通过百分比:75%
  • 失败百分比(预期):20%
  • 失败百分比(意外):5%

您基本上会用一些元数据标记您希望失败(由于某些缺陷)的任何测试用例。这可确保您在测试结束时仍能看到失败结果,但会立即知道是否有您未预料到的新失败。这似乎占据了上述 2 个提案中最好的部分。

有没有人有管理这个的最佳实践?

4

7 回答 7

6

我会把你的测试用例留在里面。根据我的经验,用类似的东西注释掉代码

// TODO:  fix test case

类似于做:

// HAHA: you'll never revisit me

严肃地说,随着您接近交付,重新访问代码中的 TODO 的愿望往往会消退,尤其是单元测试之类的事情,因为您正专注于修复代码的其他部分。

将测试留在您的“三态”解决方案中。但是,我强烈建议尽快修复这些案例。我对不断提醒的问题是,人们看到它们后,往往会掩盖它们并说“哦,是的,我们总是遇到这些错误......”

举个例子——在我们的一些代码中,我们引入了“可跳过断言”的概念——断言可以让您知道存在问题,但允许我们的测试人员跳过它们进入其余的代码。我们发现 QA 开始说诸如“哦,是的,我们一直得到那个断言,我们被告知它是可跳过的”,并且没有报告错误。

我想我的建议是还有另一种选择,即修复您的测试用例立即发现的错误。不这样做可能有实际的理由,但从长远来看,现在养成这种习惯可能会更有益。

于 2008-10-01T02:04:28.487 回答
6

立即修复错误。

如果它太复杂而无法立即完成,那么它可能是一个太大的单元,无法进行单元测试。

丢失单元测试,并将缺陷放入您的错误数据库中。这样它就具有可见性,可以优先考虑,等等。

于 2008-10-01T03:54:38.643 回答
2

我通常在 Perl 和 Perl 的 Test::* 模块中工作,允许您插入 TODO 块:

TODO: {
  local $TODO = "This has not been implemented yet."

  # Tests expected to fail go here
}

在测试运行的详细输出中,$TODO 中的消息被附加到 TODO 块中每个测试的通过/失败报告中,以解释为什么预期会失败。对于测试结果的汇总,所有的 TODO 测试都被视为成功,但是,如果有任何实际返回成功的结果,汇总也会将这些结果进行计数,并报告意外成功的测试数量。

那么,我的建议是找到具有类似功能的测试工具。(或者只是使用 Perl 进行测试,即使被测试的代码是另一种语言......)

于 2008-10-01T02:49:51.887 回答
1

我倾向于使用Ignore属性(这是使用NUnit)将这些留在其中 - 在测试运行输出中提到了测试,因此它是可见的,希望这意味着我们不会忘记它。考虑在“忽略”消息中添加问题/票证 ID。这样,当潜在问题被认为成熟时,它就会得到解决 - 立即修复失败的测试会很好,但有时小错误必须等到时机成熟。

我考虑过Explicit属性,它的优点是无需重新编译即可运行,但它不需要“原因”参数,并且在我们运行的 NUnit 版本中,测试不显示在输出中作为未运行。

于 2008-10-01T01:56:32.170 回答
1

我们做了以下工作: 在测试上设置层次结构。

示例:您必须测试 3 件事。

  • 测试登录(登录,检索用户名,获取“最后登录日期”或熟悉的东西等)
  • 测试数据库检索(搜索给定的“schnitzelmitkartoffelsalat” - 标签,搜索最新标签)
  • 测试网络服务(连接、获取版本号、检索简单数据、检索详细数据、更改数据)

每个测试点都有子点,如括号中所述。我们将这些分层。举最后一个例子:

3. Connect to a web service
    ...
3.1. Get the version number
    ...
3.2. Data:
    3.2.1. Get the version number
    3.2.2. Retrieve simple data
    3.2.3. Retrieve detailed data
    3.2.4. Change data

如果一个点失败(在开发过程中)给出一个准确的错误信息。即3.2.2。失败的。那么测试单元将不会执行 3.2.3 的测试。和 3.2.4。. 这样你会得到一个(确切的)错误消息:“3.2.2 failed”。因此让程序员(首先)解决该问题而不是处理 3.2.3。和 3.2.4。因为这行不通。

这有助于澄清问题并明确首先必须做什么。

于 2008-10-01T02:18:49.043 回答
0

我认为您需要一个 TODO 观察器,它可以从代码库中生成“TODO”注释。TODO您的测试元数据。它是已知故障消息前面的一行,并且很容易关联。

TODO 很好。使用它们。通过定期将它们实际放入积压工作来积极管理它们。

于 2008-10-01T02:31:52.257 回答
0

Joel 的“12 Steps to Better Code”中的 #5是在编写新代码之前修复错误:

当您在第一次尝试运行它时发现代码中有错误时,您将能够立即修复它,因为所有代码仍然在您的脑海中记忆犹新。

如果您在几天前编写的某些代码中发现了一个错误,您将需要一段时间才能找到它,但是当您重新阅读您编写的代码时,您会记住所有内容并且您将能够修复在合理的时间内出错。

但是,如果您在几个月前编写的代码中发现了一个错误,您可能已经忘记了该代码的很多内容,而且修复起来要困难得多。到那时你可能正在修复别人的代码,他们可能正在 Aruba 度假,在这种情况下,修复 bug 就像科学:你必须缓慢、有条不紊、一丝不苟,而且你无法确定如何发现治疗方法需要很长时间。

而且,如果您在已经发布的代码中发现了一个错误,那么您将花费巨额费用来修复它。

但是,如果您真的想忽略失败的测试,请在您使用的任何测试框架中使用 [Ignore] 属性或其等效属性。在 MbUnit 的 HTML 输出中,忽略的测试显示为黄色,而失败的测试显示为红色。这使您可以轻松地注意到一个新失败的测试,但您不会忘记已知失败的测试。

于 2008-10-01T03:34:50.873 回答