【问题标题】:Unit-testing coverage policy, test quality concerns单元测试覆盖政策,测试质量问题
【发布时间】:2011-04-02 01:00:20
【问题描述】:

我们公司正试图通过对自动化单元测试强制执行最小功能覆盖来提高软件质量。这已经是一个很好的起点,至少可以编写一些测试并使它们自动化(尽管最好进行分支或决策覆盖)。

我主要关心的是在使用此政策后将要编写的测试结果。我经常看到这样的规则导致大量的空测试(即没有断言)或一些维护噩梦类型的集成测试。我发现以下与主题相关的 SO 问题,但这些问题更多地集中在覆盖率上:

Pitfalls of code coverage

What is a reasonable code coverage % for unit tests (and why)?

相反,我想获得帮助或见解,我们如何才能避免糟糕的测试质量。所以这里有几个最糟糕的单元测试禁忌,以及我已经想到的避免它们的方法:

1) 空测试

  • 也对测试代码进行代码审查
  • 当我们使用测试框架时,断言是通过使用固件宏来完成的。也许我们可以编写一些工具来计算被测类的每个方法调用的断言比率。还不知道,什么才是足够好的比例。

2) 集成测试

  • 再次审核
  • 也许是一些代码分析工具来检查测试代码的依赖关系 生产代码。测试班应该 有很少量 对其他类的依赖(除了 到一个正在测试)的 经过测试的系统。

有很多团队,我并不完全相信团队内部的审查在所有情况下都足够了。因此,我会对自动化质量保证的方法更感兴趣。

TIA,卢特库

【问题讨论】:

  • 有什么问题?您是在问是否应该审查测试?
  • 最后一句是重点。我想知道是否可以使用任何工具来避免质量不佳的单元测试。但基本上任何关于这方面的一般知识都会受到赞赏。
  • 如果您知道如何让团队中的其他人审查测试代码,那么请发布...
  • 最好的答案是您明确禁止的答案:代码审查。 (实际上,还有一个更好的答案,那就是结对编程——您不仅可以获得即时代码审查,而且如果您每天或两天轮换结对,您还可以非常有效地传播知识。)
  • “我不完全相信团队内部审查在所有情况下都足够了” 真的吗?为什么不?它适用于大多数人。为什么它对你不起作用?你有证据吗?

标签: unit-testing code-coverage


【解决方案1】:

我经历过这个过程,帮助公司的自动化测试从分散式/零散式测试变成了非常有用且质量更高的测试。

我发现尝试将指标作为质量的主要驱动因素没有抓住重点。首先,这是一个人的问题。你不能无缘无故地让别人相信某事,就像没有支持你不能神奇地让他们擅长某事一样。

简短而困难的答案是,要提高测试质量,您需要将测试代码视为一等公民。人们不会在自动化测试方面做得很好,除非他们可以被推销并得到支持来提高他们的技能。很多人绕开这个问题,但事实是自动化测试很难做好,很多开发人员不会“明白”或接受这是一项需要学习的技能;更糟糕的是,许多人会默默地挣扎,拒绝寻求帮助。

未能证明其好处会导致测试乏善可陈,这会反馈给开发人员,使他们认为测试无用并且找不到错误。如果开发人员将测试视为一件苦差事并将其投入其中,那么他们就已经认为它是无用的——它变成了一个自我实现的预言和一个彻头彻尾的苦差事。我从经验中知道,没有什么比编写代码然后编写所有测试来达到一个神奇的覆盖目标更糟糕的了。到那时,不仅代码无法测试,而且就像在周日晚上完成所有学校作业一样——没有乐趣。

您需要了解为什么单元测试可以提供帮助,什么是好的/正确的/可理解的/可维护的/等等。单元测试看起来像。您可以通过教育、演示、结对编程、代码审查等方式做到这一点。如果你只是设置一个硬性限制并告诉人们你希望他们达到它,他们可能会反感它,然后玩弄系统。注意:这不是一件容易的事!让可疑的开发人员看到其中的价值并开始编写非疯狂测试需要花费大量时间。没有一个单一的“啊哈”时刻是你可以依靠的。已经进行的研究证明自动化测试可以成为一种有价值的开发工具,但是很多开发人员都是教条主义的。有些人永远不会接受这个想法。

我发现结对编程非常有效。找一个可以轻松测试的隔离组件,或者用它们编写一些测试。完成编写测试、使测试通过、重构测试和生产代码以消除问题并使它们更具可读性的过程。随着时间的推移,培养他们的技能,向他们展示测试工具箱中最常见的技术。随着时间的推移,尝试各种技术,例如使用良好的命名实践、命名常量、工厂方法、测试数据构建器、BDD 风格的“夹具作为上下文”。向他们展示如何通过在修复错误之前编写失败的测试来证明错误存在。强调创建良好测试的最重要原则!

最终目标应该是所有代码团队都同意一些经验法则,例如“要获得批准,所有故事都必须经过充分测试并通过代码审查”。如果自动化测试对于给定的工作(例如原型)没有价值/不可行,那 100% 没问题,但这应该是例外,而不是规则。

拥有受人尊敬的代码主管,他们将与他们的团队合作实现这一目标,这一点至关重要。如果您无法从所有潜在客户那里获得支持,那么您就有一个大问题。

您可以使用诸如 NDepend(或您选择的语言的变体)之类的代码度量工具来增强您的方法,该工具提供的功能包括列出没有良好测试覆盖率的最复杂/使用过的代码,或者缺乏覆盖率的区域在签入之间变化最大。

祝你好运。

【讨论】:

  • +1:“试图将指标应用为质量的主要驱动因素没有抓住重点”
【解决方案2】:

获得良好测试的最佳方法是练习测试驱动开发,这意味着首先测试。它分为几个步骤:

  1. 编写足够的测试以使其失败
  2. 编写足够的生产代码以通过测试
  3. 3 次重复,随走随折射

当然,这是一个巨大的简化,TDD 是一个很大的主题,但是没有它,我还没有看到好的快速易于维护的测试。另一个关键是开发人员需要想要这样做,他们需要了解它如何让他们的生活更轻松,如何让他们在以后更改代码时解放出来。如果开发人员不愿意开始测试,或者如果他们不知道如何编写测试(按照 SOLID 和 FIRST 原则管理依赖项),那么您施加什么规则可能并不重要。

【讨论】:

  • 不幸的是,让开发人员了解单元测试的好处通常需要很长时间,然后他们需要很长时间才能学会如何正确地进行测试。 TDD 可能是缩短此过程的一种方法,但同时可能会产生大量废话测试(无需观看)。
  • @lutku:TDD 不能产生废话测试。
【解决方案3】:

有一个称为 CRAP 的指标,它结合了复杂性分析和覆盖率

http://blog.businessofsoftware.org/2007/09/alberto-savoia-.html

基本上,每个函数都有一个分数,如果函数复杂或没有覆盖,函数会变得更糟。这意味着您不能通过测试 get/set 方法来降低分数——您必须查看复杂的函数。您可以分解它们(重构)或测试它们以获得覆盖。

该视频解释了为什么这是一个很难衡量游戏的指标。

它对 Null 测试没有帮助,但它有助于将测试重点放在您可以从中获得更多收益的地方。

【讨论】:

    【解决方案4】:

    是的,这是一个非常困难的问题(另请参阅博文avoid false-positives vs. false-negatives

    除了上面讨论的技术之外,还有mutation-testing,您可以在其中检查测试套件的质量。在 wiki 页面的一些参考资料中,您可以看到一些提示如何帮助自己对现有框架进行自定义扩展。我曾经尝试过Jester,它很好但也很慢,不幸的是该项目目前似乎没有那么活跃......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 2017-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多