由于《
Pycharm学习笔记01:PyCharm介绍
》提出此名词,比较陌生。
Code coverage
is a metric that can help you understand how much of your source is tested. It’s a very useful metric that can help you assess the quality of your test suite, and we will see here how you can get started with your projects.
代码覆盖率
是一个指标,可以帮助您了解测试了多少源代码。这是一个非常有用的指标,可以帮助您评估测试套件的质量,我们将在这里看到如何开始您的项目。
代码覆盖率是如何计算的?
代码覆盖工具将使用一个或多个标准来确定您的代码在测试套件的执行过程中是如何被执行的。您可能会在覆盖率报告中看到的常见指标包括:
-
函数覆盖
: 定义的函数有多少被调用了。 -
语句覆盖率
: 程序中执行了多少条语句。 -
分支覆盖率
:控制结构(例如,if 语句)的分支数量已被执行。 -
条件覆盖
:有 多少布尔子表达式已经被测试为真值和假值。 -
行覆盖率
: 已经测试了多少行源代码。
这些指标通常表示为实际测试的项目数、在您的代码中找到的项目和覆盖百分比(测试的项目/找到的项目)。
这些指标是相关的,但又是不同的。在下面的简单脚本中,我们有一个 Javascript 函数检查参数是否是 10 的倍数。稍后我们将使用该函数检查 100 是否是 10 的倍数。这将有助于理解两者之间的区别功能覆盖和分支覆盖。
coverage-tutorial.js
function isMultipleOf10(x) { if (x % 10 == 0) return true; else return false; } console.log(isMultipleOf10(100));
我们可以使用覆盖工具
istanbul
来查看运行此脚本时执行了多少代码。运行覆盖率工具后,我们会得到一份覆盖率报告,其中显示了我们的覆盖率指标。我们可以看到,虽然我们的 Function Coverage 是 100%,但我们的 Branch Coverage 只有 50%。我们还可以看到 istanbul 代码覆盖率工具没有计算 条件覆盖率 指标。
这是因为当我们运行我们的脚本时,else 语句还没有被执行。如果我们想获得 100% 的覆盖率,我们可以简单地添加另一行,本质上是另一个测试,以确保使用 if 语句的所有分支。
coverage-tutorial.js
function isMultipleOf10(x) { if (x % 10 == 0) return true; else return false; } console.log(isMultipleOf10(100)); console.log(isMultipleOf10(34)); // This will make our code execute the "return false;" statement.
第二次运行coverage工具将显示,由于底部的两个console.log()语句,100%的源代码都被覆盖了。
在本例中,我们只是在终端中记录结果,但在运行测试套件时应用相同的原则。代码覆盖率工具将监视测试套件的执行,并告诉您有多少语句、分支、函数和行是作为测试的一部分运行的。
代码覆盖率入门
为您的项目找到合适的工具
根据您使用的语言,您可能会找到几个选项来创建覆盖率报告。下面列出了一些常用工具:
-
Java:
Atlassian Clover
,
Cobertura
,
JaCoCo
-
Javascript:
istanbul
,
Blanket.js
-
PHP:
PHPUnit
-
Python:
Coverage.py
-
Ruby:
SimpleCov
有些工具(如istanbul)会将结果直接输出到终端,而另一些工具可以生成完整的HTML报告,让您了解代码中哪些部分缺少覆盖。
你的目标覆盖率是多少?
在代码覆盖率方面没有万灵药,如果应用程序的关键部分没有被测试,或者如果现有的测试不够健壮,无法预先正确捕获故障,那么覆盖率的高百分比仍然会有问题。尽管如此,
人们普遍认为80%的覆盖率是一个很好的目标
*。试图达到更高的覆盖率可能代价高昂,但没有必要产生足够的效益。
第一次运行覆盖率工具时,您可能会发现覆盖率相当低。如果你刚刚开始测试,这是一个正常的情况,你不应该感到压力,以达到80%的覆盖率马上。原因是匆忙达成覆盖率目标可能会促使您的团队编写符合每一行代码的测试,而不是编写基于应用程序业务需求的测试。
例如,在上面的例子中,通过测试100和34是否是10的倍数,我们达到了100%的覆盖率。但是如果我们用字母而不是数字来调用函数呢?我们应该得到正确/错误的结果吗?或者我们应该得到一个例外?让团队有时间从用户的角度考虑测试,而不仅仅是查看代码行,这一点很重要。代码覆盖率不会告诉您是否缺少源代码中的内容。
首先关注单元测试
单元测试包括确保应用程序使用的类和组件的各个方法正常工作。它们通常实现起来很便宜,运行起来也很快,并为您提供了平台基础稳固的总体保证。快速增加代码覆盖率的一个简单方法是从添加单元测试开始,因为根据定义,单元测试应该帮助您确保测试套件能够覆盖所有代码行。
使用覆盖率报告识别测试中的关键未命中
很快,您的代码中将包含如此多的测试,以至于您不可能知道在执行测试套件的过程中检查了应用程序的哪个部分。当您获得红色构建时,您将知道什么会中断,但是您很难理解哪些组件通过了测试。
这是覆盖率报告可以为您的团队提供可操作指导的地方。大多数工具都允许您深入到覆盖率报告中,查看测试未覆盖的实际项目,然后使用这些项目来确定应用程序中仍需要测试的关键部分。
准备就绪后,将代码覆盖率作为持续集成流程的一部分
当您建立了持续集成(CI)工作流后,如果您没有达到足够高的覆盖率,您可能会开始失败测试。当然,正如我们前面所说的,将失败阈值设置得太高是不合理的,90%的覆盖率很可能会导致构建失败很多。如果你的目标是80%覆盖,你可以考虑在70%设置一个失败阈值作为你的CI文化的安全网。
再一次,要小心避免发送错误的消息,因为向您的团队施加压力以获得良好的覆盖率可能会导致糟糕的测试实践。
好的覆盖率并不等于好的测试
获得良好的测试文化首先要让您的团队了解当有人正确使用应用程序时,以及当有人试图破坏应用程序时,应用程序应该如何运行。代码覆盖率工具可以帮助您理解下一步应该将注意力集中在哪里,但它们不会告诉您现有的测试是否足够健壮,能够应对意外行为。
实现高覆盖率是一个很好的目标,但它应该与一个健壮的测试套件相结合,以确保单个类不会被破坏,并验证系统的完整性。