8

我最近花了大约 70% 的时间编写功能编写集成测试。有一次,我在想“该死,测试它这么辛苦,我知道我这里没有错误,为什么我要这么努力呢?让我们先浏览一下测试并完成它......”</p>

五分钟后,测试失败。详细检查表明这是我们正在使用的第 3 方库中的一个重要的未知错误。

所以......你在哪里划定你的界限来测试什么,什么是信仰?您是否测试了所有内容,或者您​​期望大多数错误的代码?

4

12 回答 12

18

在我看来,在测试方面务实很重要。将您的测试工作优先考虑最有可能失败的事情,和/或最重要的事情不会失败(即考虑概率和后果)。

想想,而不是盲目地遵循一个指标,比如代码覆盖率。

当您对测试套件和代码感到满意时停止。当(如果?)事情开始失败时,返回并添加更多测试。

于 2009-07-10T14:02:42.197 回答
4

当您不再害怕对代码进行中到大的更改时,那么您很可能已经进行了足够的测试。

于 2009-07-10T14:07:56.043 回答
3

好问题!

首先 - 听起来你广泛的集成测试得到了回报:)

根据我的个人经验:

  • 如果它是一个“绿色领域”的新项目,我喜欢强制执行严格的单元测试并设计一个彻底(尽可能彻底)的集成测试计划。
  • 如果它的现有软件测试覆盖率很差,那么我更喜欢设计一组集成测试来测试特定/已知功能。然后,随着代码库的进一步发展,我介绍了测试(单元/集成)。

多少才够?棘手的问题 - 我认为永远都不够!

于 2009-07-10T14:04:24.033 回答
3

“太多的东西就够了。”

我不遵循严格的 TDD 实践。我尝试编写足够的单元测试来覆盖所有代码路径并练习我认为重要的任何边缘情况。基本上,我试图预测可能出现的问题。我还尝试将我编写的测试代码的数量与我认为被测代码的脆弱程度或重要性相匹配。

我在一个方面是严格的:如果发现了一个 bug,我首先编写一个测试,测试该 bug 并失败,进行代码更改,并验证测试是否通过。

于 2009-07-10T14:04:39.680 回答
3

Gerald Weinberg 的经典著作《计算机编程心理学》中有很多关于测试的好故事。我特别喜欢第 4 章“将编程作为一项社交活动”中的一个,“Bill”要求一位同事检查他的代码,他们在仅 13 条语句中发现了 17 个错误。代码审查提供了额外的眼睛来帮助发现错误,你使用的眼睛越多,你找到非常微妙的错误的机会就越大。就像 Linus 说的,“只要有足够的眼球,所有的 bug 都很浅”,你的测试基本上是机器人的眼睛,它会在白天或晚上的任何时间查看你的代码,并让你知道一切是否仍然是 kosher。

多少测试就足够了,这取决于您是从头开始开发还是维护现有系统。

从头开始时,您不希望花费所有时间编写测试并最终无法交付,因为您能够编写代码的 10% 的功能都经过了详尽的测试。将有一些优先级要​​做。一个例子是私有方法。由于私有方法必须由以某种形式(公共/包/受保护)可见的代码使用,因此私有方法可以被认为包含在更可见方法的测试中。如果私有代码中有一些重要或晦涩的行为或边缘情况,则需要在此处包含一些白盒测试。

测试应该帮助您确保 1) 了解需求,2) 通过编写可测试性代码来遵守良好的设计实践,以及 3) 知道以前存在的代码何时停止工作。如果您无法描述某个功能的测试,我敢打赌您对该功能的理解不够好,无法清晰地对其进行编码。使用单元测试代码会迫使你做一些事情,比如将数据库连接或实例工厂等重要的事情作为参数传递,而不是屈服于让类自己做太多事情并变成“上帝”对象的诱惑。让您的代码成为您的金丝雀意味着您可以自由地编写更多代码。当先前通过的测试失败时,这意味着两件事之一,

使用现有代码时,您应该能够证明所有已知场景都已涵盖,以便在下一个更改请求或错误修复出现时,您可以自由地挖掘您认为合适的任何模块,而无需担心,“如果我破坏了某些东西怎么办?这会导致花费更多的时间来测试甚至是小的修复,然后才需要实际更改代码。

因此,我们无法为您提供硬性和快速的测试数量,但您应该争取一定程度的覆盖率,这会增加您对不断进行更改或添加功能的能力的信心,否则您可能已经达到收益递减的地步.

于 2009-07-10T16:22:44.760 回答
1

如果您或您的团队一直在跟踪指标,您可以看到随着软件生命周期的进展,每次测试都发现了多少错误。如果您已经定义了一个可接受的阈值,其中测试所花费的时间不能证明发现的错误数量是合理的,那么这就是您应该停止的点。

您可能永远不会找到 100% 的错误。

于 2009-07-10T14:02:45.190 回答
0

我花了很多时间在单元测试上,但很少在集成测试上。单元测试允许我以结构化的方式构建一个特性。现在你有了一些很好的文档和回归测试,可以在每个构建中运行

集成测试是另一回事。它们很难维护,并且根据定义集成了许多不同的功能,通常与难以使用的基础设施一起使用。

于 2009-07-10T14:03:44.673 回答
0

与生活中的一切一样,它受到时间和资源的限制,并且相对于其重要性而言。理想情况下,您会测试您合理认为可能会破坏的所有内容。当然,您的估计可能是错误的,但是过度测试以确保您的假设正确取决于错误的严重程度与继续进行下一个功能/发布/项目的需要。

注意:我的回答主要针对集成测试。TDD 非常不同。它之前在 SO 上有所介绍,当您没有更多功能要添加时,您将停止测试。TDD 是关于设计,而不是错误发现。

于 2009-07-10T14:05:24.237 回答
0

我测试一切。我讨厌它,但它是我工作的重要组成部分。

于 2009-07-10T14:00:02.277 回答
0

在成为开发人员之前,我在 QA 工作了 1.5 年。

您永远无法测试所有内容(我在训练时被告知单个文本框的所有排列需要比已知宇宙更长的时间)。

作为开发人员,您没有责任了解或说明哪些是重要的测试和哪些不应该测试的优先级。最终产品的测试和质量是一项责任,但只有客户才能有意义地说明功能的优先级,除非他们明确将此责任赋予您。如果没有 QA 团队并且您不知道,请让项目经理找出并确定优先级。

测试是一种降低风险的练习,客户/用户将知道什么是重要的,什么不是。使用极限编程中的测试优先驱动开发会很有帮助,因此您有一个良好的测试基础,并且可以在更改后进行回归测试。

重要的是要注意,由于自然选择,代码可能对测试“免疫”。Code Complete 表示,在修复缺陷并为其编写测试用例并寻找类似缺陷时,为与其相似的缺陷编写测试用例也是一个好主意。

于 2009-07-10T14:10:26.803 回答
0

我更喜欢尽可能多地进行单元测试。最大的副作用之一(除了提高代码质量和帮助避免一些错误)是,在我看来,对单元测试的高期望要求人们更好地改变他们编写代码的方式。至少,这对我来说是这样的。

我的课程更有凝聚力,更容易阅读,也更灵活,因为它们被设计为功能性可测试性。

也就是说,我使用 junit 和 cobertura(用于 Java)默认单元测试覆盖率要求为 90%(行和分支)。当我觉得由于特定类的性质(或 cobertura 中的错误)而无法满足这些要求时,我会例外。

单元测试从覆盖开始,当你用它们来真实地测试边界条件时,它真的对你有用。对于如何实现该目标的建议,其他答案都是正确的。

于 2009-07-10T14:18:28.837 回答
0

本文就不同数量用户的用户测试的有效性提供了一些非常有趣的见解。它表明您可以在只有三个用户测试应用程序的情况下找到大约三分之二的错误,而在只有五个用户的情况下,您可以找到多达 85% 的错误。

单元测试很难赋予离散值。要记住的一个建议是,单元测试可以帮助您整理关于如何开发正在测试的代码的想法。一旦您编写了一段代码的需求并有办法可靠地检查它,您就可以更快、更可靠地编写它。

于 2009-07-10T14:19:24.997 回答