什么可以作为代码覆盖的替代指标?

时间:2009-06-26 07:13:30

标签: unit-testing code-coverage code-metrics

代码覆盖率可能是最具争议的代码度量标准。有人说,你必须达到80%的代码覆盖率,其他人说,它是肤浅的,并没有说明你的测试质量。 (见Jon Limjap's good answer on "What is a reasonable code coverage % for unit tests (and why)?"。)

人们倾向于衡量一切。他们需要比较,基准等。
项目团队需要一个指针,他们的测试有多好。

那么代码覆盖的替代方案是什么?什么是一个比“我触及这行代码”更多的好指标? 有真正的替代方案吗?

15 个答案:

答案 0 :(得分:22)

如果您正在寻找一些有用的指标来告诉您代码的质量(或缺少),您应该查看以下指标:

  1. Cyclomatic Complexity
    • 这是衡量方法复杂程度的指标。
    • 通常10和更低是好的,11-25是差的,更高是可怕的。
  2. 嵌套深度
    • 这是衡量方法中嵌套范围的数量的指标。
    • 通常4和更低是好的,5-8是差的,更高是可怕的。
  3. 关系凝聚力
    • 这是衡量包或装配中类型的相关程度的指标。
    • 关系凝聚力在某种程度上是一个相对指标,但也是有用的。
    • 可接受的水平取决于公式。鉴于以下内容:
      • R:包/程序集中的关系数
      • N:包/程序集中的类型数
      • H:类型之间关系的凝聚力
    • 式:H =(R + 1)/ N
    • 鉴于上述公式,可接受的范围是1.5-4.0
  4. 缺乏方法的凝聚力(LCOM)
    • 这是衡量一个阶级凝聚力的指标。
    • 类的内聚力衡量每个方法引用的字段数。
    • 很好地表明您的班级是否符合单一责任校长。
    • 公式:LCOM = 1 - (总和(MF)/ M * F)
      • M:班级中的方法数量
      • F:类
      • 中的实例字段数
      • MF:访问特定实例字段的类中的方法数
      • sum(MF):所有实例字段的MF总和
    • 完全凝聚力的类将具有0的LCOM。
    • 完全无粘性的类将具有1的LCOM。
    • 你越接近0,你的班级就越有凝聚力和可维护性。
  5. 这些只是NDepend(.NET指标和依赖关系映射实用程序)可以为您提供的一些关键指标。我最近在代码指标方面做了很多工作,这4个指标是我们发现最有用的核心关键指标。 NDepend还提供了其他几个有用的指标,包括Efferent&传入耦合和抽象性&不稳定性可以很好地衡量代码的可维护性(以及你的NDepend是否称为痛苦区域或无用区域。)

    即使您不使用.NET平台,我也建议您查看NDepend metrics page。您可以使用很多有用的信息在您开发的任何平台上计算这些指标。

答案 1 :(得分:7)

Crap4j是我所知道的一个相当好的指标......

它是Change Risk Analysis and Predictions软件度量标准的Java实现,它结合了自动化测试中的圈复杂度和代码覆盖率。

答案 2 :(得分:2)

错误指标也很重要:

  • 进入的错误数量
  • 已解决的错误数

例如,检测错误是否解决得不像新的错误那样快。

答案 3 :(得分:2)

代码覆盖率只是一个指标,有助于指出测试中根本没有执行的行,这非常有趣。如果您的代码覆盖率达到80%左右,那么查看其余20%的行是否有意义,以确定您是否缺少某些用例。如果你看到“aha,如果我传递一个空向量就会执行此行”,那么你实际上可以编写一个传递空向量的测试。

作为替代方案,我可以想到,如果你有一个带有用例和功能要求的规范文档,你应该将单元测试映射到它们,看看FR覆盖了多少UC(当然它应该是100%) UT覆盖了多少FR(同样,它应该是100%)。

如果你没有有规格,谁在乎呢?任何发生的事情都可以:)

答案 4 :(得分:2)

如何在项目中观察代码覆盖率趋势?

正如许多其他指标的情况一样,单个数字并不是很多。

例如,如果“我们的Checkstyle规则符合78.765432%”,则很难说是否存在问题。如果昨天的合规率是100%,我们肯定遇到了麻烦。如果昨天是50%,我们可能做得很好。

当代码覆盖率越来越低时,我总是感到紧张。有些情况下这是可以的,因此在查看图表和数字时你无法关闭。

BTW,声纳(http://sonar.codehaus.org/)是观看趋势的绝佳工具。

答案 5 :(得分:2)

在它上面使用代码覆盖主要是没有意义的,如果你正在寻找不必要的代码,它只给你提供见解。

将它与单元测试结合使用并以100%覆盖率为目标,将告诉您所有“已测试”部件(假设它们都已成功完成)按单元测试中的规定工作。

从技术设计/功能设计编写单元测试,具有100%覆盖率和100%成功测试将告诉您该程序的工作方式与文档中描述的相同。

现在你唯一需要的是良好的文档,特别是功能设计,程序员不应该写,除非他是该特定领域的专家。

答案 6 :(得分:1)

(代码行)/(测试用例数)怎么样?不是很有意义(因为它取决于LOC),但至少它很容易计算。

另一个可能是(测试用例数)/(方法数)。

答案 7 :(得分:1)

根据经验,缺陷注入率按比例跟踪代码产量,它们通常都遵循瑞利分布曲线。
在某些时候,您的缺陷检测率将达到峰值,然后开始减少 该顶点占已发现缺陷的40% 通过简单的回归分析,您可以估计产品在峰值后的任何点上仍有多少缺陷 这是Lawrence Putnam模型的一个组成部分。

答案 8 :(得分:1)

情景报道。

我认为你真的不想拥有100%的代码覆盖率。测试说,简单的getter和setter看起来像浪费时间。

代码总是在某些上下文中运行,因此您可以列出尽可能多的方案(取决于问题的复杂性,有时甚至是所有方案)并测试它们。

示例:

// parses a line from .ini configuration file
// e.g. in the form of name=value1,value2
List parseConfig(string setting)
{
    (name, values) = split_string_to_name_and_values(setting, '=')
    values_list = split_values(values, ',')
    return values_list
}

现在,您有许多方案需要测试。其中一些:

  • 传递正确的值

  • 列出项目

  • 传递null

  • 传递空字符串

  • 传递格式错误的参数

  • 使用前导或结尾逗号传递字符串,例如name = value1,或name =,value2

只运行第一次测试可能会给您(取决于代码)100%的代码覆盖率。但是你没有考虑所有的可能性,所以这个指标本身并没有告诉你太多。

答案 9 :(得分:1)

我写了一篇关于为什么High Test Coverage Ratio is a Good Thing Anyway

的博文

我同意:当一部分代码由测试执行时,并不意味着这部分代码产生的结果的有效性由测试验证

但是,如果你在测试执行期间大量使用合同检查状态有效性,那么高测试覆盖率将意味着大量的验证。

答案 10 :(得分:1)

代码覆盖率中的值是它让您了解测试所执行的操作。 短语“代码覆盖”通常用于表示语句覆盖,例如“我的代码(在行中)已经执行了多少”,但实际上有超过一百种“覆盖”。这些其他版本的覆盖范围试图提供更复杂的视图来表示执行代码的意义。

例如,条件覆盖率测量条件表达式的多个单独元素已被执行。这与声明范围不同。 MC / DC “修改条件/决策覆盖”确定是否所有条件表达式的元素都已被证明可以控制条件的结果,并且FAA要求其用于飞行器软件。路径覆盖率测量通过代码执行的可能执行路径的数量。这是一个比语句覆盖更好的度量,因为路径实际上代表了代码中的不同情况。哪种措施最好使用取决于您对测试有效性的关注程度。

维基百科很好地讨论了测试覆盖的许多变化。 http://en.wikipedia.org/wiki/Code_coverage

答案 11 :(得分:1)

这没有被提及,但是给定的代码或方法文件(通过查看版本控制历史记录)中的更改量很有意义,特别是当您为经过严格测试的代码构建测试套件时。将测试重点放在您经常更改的代码部分上。留下你不需要的东西。

注意原因和结果的逆转。您可能会避免更改未经测试的代码,并且可能更倾向于更改测试代码。

答案 12 :(得分:0)

SQLite是一个extremely well-tested库,您可以从中提取各种指标。

  

从版本3.6.14开始(报告中的所有统计信息都与SQLite版本相对),SQLite库包含大约63.2个KSLOC的C代码。 (KSLOC意味着成千上万的“源代码行”,换句话说,代码行不包括空白行和注释。)相比之下,该项目的测试代码和测试脚本数量为715倍--KSLOC为45261.5。

最后,最重要的是,这些可能的指标似乎与简单的声明一样重要,“它满足所有要求”。 (所以在实现目标的过程中不要忽视这一目标。)

如果您想要判断团队的进展,那么您必须制定个人要求。这给了你一些指向和说“这个已经完成,这个不是”的东西。它不是线性的(解决每个要求需要不同的工作),并且你可以线性化它的唯一方法是问题是否已经在其他地方得到解决(因此你可以按要求量化工作)。

答案 13 :(得分:0)

我喜欢收入,销售数字,利润。它们是代码库的非常好的指标。

答案 14 :(得分:0)

可能不仅测量单元测试所覆盖(触摸)的代码,而且还可以评估断言的好坏。

一个易于实现的指标是测量Assert.AreEqual

的大小

您可以创建自己的Assert实现,调用Assert.AreEqual并测量作为第二个参数传递的对象的大小。