代码覆盖率测量

学习目标

  • 了解代码覆盖率指标

  • 生成和检查代码覆盖率报告

  • 找到尚未被自动化测试覆盖的代码

  • 强制执行代码覆盖率阈值和提高代码覆盖率

代码覆盖率(也称为测试覆盖率)告诉您通过运行单元测试和集成测试来执行的代码部分。代码覆盖率通常以百分比形式表示,例如,79%语句,53%分支,74%函数,78%行数。

语句广义上是控制结构,例如iffor,以及由分号分隔的表达式。分支是指 if (…) {…} else {…}… ? … : … 条件的两个分支。函数和行不言自明。

覆盖率报告

在Angular的Karma和Jasmine设置中,使用 伊斯坦布尔(Istanbul) 来测量测试覆盖率。Istanbul重写要测试的代码,记录是否调用了语句、分支、函数和行。然后它生成一个全面的测试报告。

要在运行测试时激活Istanbul,请添加--code-coverage参数:

ng test --code-coverage

在测试完成后,Istanbul会将报告保存在位于Angular项目目录下的coverage目录中。

该报告是一组HTML文件,您可以使用浏览器打开。首先,在您选择的浏览器中打开coverage/index.html文件。

Flickr搜索示例的报告如下所示:

code coverage flickr search

Istanbul为每个目录和每个文件创建了一个HTML页面。通过跟随链接,您可以查看每个文件的报告。

例如,Flickr搜索的 photo-item.component.ts 的覆盖率报告如下:

code coverage photo item

报告呈现了带有调用次数信息的源代码注释。在上面的示例中,除了一个不相关的else分支(用“E”标记)之外,代码完全被覆盖。

规范 it('focusses a photo on click', () ⇒ {…}) 在点击照片项来测试focusPhoto输出是否发出。让我们故意禁用这个规范,以查看影响。

code coverage photo item uncovered

从上面的覆盖率报告中可以看出,handleClick方法从未被调用过。一个关键的组件行为没有进行测试。

如何使用覆盖率报告

现在我们知道如何生成报告,那么我们应该如何使用它呢?

在章节 适量的测试 中,我们已经确定了代码覆盖率作为一个有用但存在缺陷的度量标准。作为一种定量的指标,代码覆盖率无法评估测试的质量。

软件测试不是一场竞赛。我们不应该为了得分而努力达到某个特定的分数。那么我们测量代码覆盖率的目的是什么呢?

找到未覆盖的代码

覆盖率报告是一个有价值的工具,你在编写测试时应该使用它。它 揭示了尚未进行测试的代码行为。该报告不仅指导您的测试,还加深了您对测试工作原理的理解。

无论您当前的覆盖率得分是多少,都可以使用报告来监控和改进您的测试实践。如 定制您的测试方法 中所述,测试应该是开发例程的一部分。新功能应包括测试,错误修复应包括一个测试作为证明和防止回归的手段。

提高覆盖率

编写新代码和修改现有代码不应降低覆盖率得分,而是逐步增加。这意味着如果您现有的测试覆盖了75%的代码行数,新代码需要至少有75%的覆盖率。否则,得分会逐渐下降。

在持续集成环境中运行单元测试和集成测试,并测量代码覆盖率是常见做法。为了强制执行特定的覆盖率得分并防止下降,您可以在 Karma配置 中配置阈值。

karma.conf.js中,您可以为语句、分支、函数和行添加全局阈值。

coverageReporter: {
  /* … */
  check: {
    global: {
      statements: 75,
      branches: 75,
      functions: 75,
      lines: 75,
    },
  },
},

在上述配置中,所有的值都设置为75%。如果覆盖率低于这个数字,即使所有的规范都通过了,测试执行也会失败。

提高标准

当新的代码添加到项目中,并且测试覆盖率优于平均水平时,您可以逐渐提高阈值,例如从75提高到75.175.275.3等等。很快,这些小的改进将累积起来。

测试覆盖率不应该是一个毫无意义的竞争,它给开发人员带来压力,并让那些未达到任意标准的人感到羞耻。测量覆盖率应该是一个可以为您自己获益的工具。请记住,编写有意义、准确的测试并不一定会增加覆盖率得分。

对于初学者和专家来说,覆盖率报告有助于设置、调试和改进他们的测试。对于经验丰富的开发人员,得分有助于保持稳定的测试实践。