如果您已经编写了测试驱动的代码已有一段时间了,那么您将了解代码覆盖率(也称为测试覆盖率)。 如果您不熟悉该术语,则有两个简短定义。 维基百科将其定义为 :
一种度量,用于描述特定测试套件运行时程序源代码的执行程度。
根据Martin Fowler的说法 ,代码覆盖范围…
…帮助您找到未测试代码的哪些位。 值得经常运行覆盖工具并查看这些未经测试的代码。
如果您还不熟悉代码覆盖率并将其作为测试过程或持续开发流程的一部分来使用,我强烈建议您学习一下。 话虽如此,今天我将开始一个分为两部分的系列,介绍代码覆盖率工具。
在第一部分中,我将逐步介绍针对当今可用的五种最受欢迎的软件开发语言的工具。 这些是PHP , Python , Go , Java和Ruby 。
在第二部分中,我将逐步介绍四个在线服务,涵盖它们提供的功能,其工作方式的概述以及各自方法的一些差异。
为了使工具的涵盖范围变得有意义,我为每种语言创建了一个小型存储库,其中包含一个适度的用户实体以及相应的五种语言的实体测试套件。 这样,您将看到的测试输出应该更有意义。 我要强调的是,代码不会改变世界,但是足以让每个工具都有基本的感觉。
这是到五个存储库的快速链接:
- 的PHP
- Python
- Ruby
- 走
- Java
的PHP
我将从PHP开始,因为这是我目前花费最多时间开发的语言。 如果您花了很多时间在PHP上,那么您将知道提供代码覆盖率的候选人是PHPUnit 。
PHP的资深测试框架已经存在了很长时间。 PHPUnit通过其PHP_CodeCoverage组件提供了代码覆盖支持,并利用了PHP的XDebug扩展 。 可以将代码覆盖率报告生成为HTML和XML文件,支持的报告格式为Clover , Crap4J和PHPUnit。
报告本身支持以下指标:
- 线,函数和方法,类和特性,操作码,分支和路径覆盖
- 变更风险反模式(CRAP)指数
CRAP指数 :
基于圈复杂度和一个代码单元的代码覆盖率计算。 不太复杂并且具有足够测试覆盖率的代码将具有较低的CRAP索引。 通过编写测试和重构代码以降低其复杂性,可以降低CRAP索引。
另外,借助docblock批注,PHPUnit支持忽略特定代码块的功能,例如无法测试的代码块或要从代码覆盖率分析中忽略的代码块。
例如,可以使用@codeCoverageIgnore
批注指示应忽略类,函数或行。 另外,您可以使用@codeCoverageIgnoreStart
和@codeCoverageIgnoreEnd
忽略一段代码。
您还可以使用批注指示功能与一种或多种方法有关。
例如,假设我们在PHP User实体中有另一个名为getUserDetails
,该方法返回所有User的详细信息。 当然,它们的名称将成为其详细信息的一部分。 鉴于此, getName
与该方法有关。 因此,我们可以添加注释@covers User::getUserDetails
以显示测试getName
与测试getUserDetails
。
因此,您可以看到PHP的代码覆盖面非常广泛,可以准确指示测试中包括哪些内容。
运行报告
假设可以将PHPUnit作为项目依赖项并安装了XDebug扩展,则可以通过以下两种方式之一生成代码覆盖率报告。
- 可以在命令行上将选项传递给PHPUnit的调用,例如通过运行:
phpunit --coverage-html tests/coverage
- 可以在日志记录部分中配置PHPUnit的配置文件phpunit.xml.dist,以指定必要的选项,如以下示例所示:
报告范例
在下图中,您可以看到HTML报告的示例。 在顶部,您可以看到表格报告,其中显示了有关文件(或文件夹)的可用覆盖范围指标; 在这种情况下,为SimpleEntities/src/User.php
。
您可以看到它涵盖了类 , 特征 , 函数 , 方法和行 。 您可以看到类构造函数和两个方法setName
和getName
具有100%的覆盖率。
作为进一步的验证,在表格报告下,您可以看到突出显示的代码。 除一行外,其余所有行均为绿色,这意味着该行代码的执行已通过测试。 黄色表示最后的代码行。 另外,还有红色,表示该行尚未测试。
Python
为了在Python中生成代码覆盖率报告,可以将多个Python测试库与Coverage.py结合使用。
简要说明一下文档 ,Coverage.py首先运行一个或多个代码文件来了解代码中执行了哪些行。 在此阶段,它运行一个跟踪函数,该函数在执行时记录每个文件和行号。
执行完成后,它将检查执行的代码以确定可以运行哪些行。 完成这两个步骤后,根据检索到的信息,它会生成一个报告,以可视化方式显示运行的内容和未运行的内容。
与许多Python库一样,如果您使用的是Linux发行版,则可以使用包管理器进行安装,也可以通过pip进行安装。 与大多数其他库相似,Coverage.py可以生成HTML和XML文件格式的报告。
由于它使用跟踪功能提取信息以生成报告,因此将其与任何其他测试库一起使用非常简单。
安装和运行报告
在示例存储库中 ,我使用了Python的UnitTest库来创建一组简单的单元测试。 要运行测试套件,我将使用命令python setup.py test
。
要生成代码覆盖率报告,首先必须调用coverage run
并将您要分析的python代码传递给它。 为此,我将运行coverage run setup.py test
,它将使Coverage.py执行并分析我的测试套件。 之后,覆盖率信息将可用,因此我现在可以运行coverage report
,该报告将覆盖率报告打印到STDOUT中。
这是一个看起来像的例子:
[simple-entity] coverage report
Name Stmts Miss Cover
-------------------------------------------------
entities/__init__.py 0 0 100%
entities/tests/__init__.py 0 0 100%
entities/tests/test_user.py 12 1 92%
entities/user.py 9 0 100%
-------------------------------------------------
TOTAL 21 1 95%
您可以看到报告中包含四个文件。 总共有95%的代码覆盖率,因为entities/tests/test_user.py
仅具有92%的代码覆盖率。 该测试适合与文本扫描工具一起使用,但不如HTML报告灵活。 这是HTML报告的示例:
如您所见,类似于PHPUnit报告,它显示了类中的语句数,测试运行了多少,未运行了多少,以及排除了多少。
Java
使用Java开发代码时,可以使用JUnit和JaCoCo代码覆盖库等 。
该项目的文档指出JaCoCo是Java的免费代码覆盖库,由EclEmma团队创建。 JaCoCo应该为基于Java VM的环境中的代码覆盖率分析提供标准技术。 重点是提供一个轻量级,灵活且文档齐全的库,以与各种构建和开发工具集成。
JaCoCo支持以下方面的报告:
- 指令范围
- 分行覆盖
- 圈复杂度
- 单独的行(对于已使用调试信息编译的类文件)
- 包含至少一条指令的非抽象方法
- 课堂报道
而且,它可以与各种构建和开发工具集成在一起,包括Ant,Maven, Eclipse , NetBeans和IntelliJ 。
JaCoCo支持以XML , HTML和CSV格式创建报告。 由于Java比大多数语言要复杂得多,而且比动态语言要复杂得多,因此有很多方法可以将JaCoCo与所选的应用程序结合使用。
相反,我将介绍如何使用Apache Maven运行测试套件。
安装Maven并在pom.xml中创建新项目之后,如果添加以下插件配置,则在从命令行调用man test
时可以生成报告。
org.jacoco
jacoco-maven-plugin
4.12
prepare-agent
prepare-agent
report
prepare-package
report
post-unit-test
test
report
target/jacoco.exec
target/jacoco-ut
target/jacoco.exec
此配置将JoCoCo 4.12作为项目插件加载,并将target/jacoco-ut
为生成报告的目录。
如果打开target/jacoco-ut/index.html
,那么您将看到一个顶级报告,如下图所示,与其他语言HTML报告非常相似。
这显示了顶级实体和文件夹的覆盖范围,报告了覆盖范围百分比,行,方法和类。 如果您深入研究类,则可以在该类中看到与该方法相同的信息,如下面的屏幕截图所示。
而且,如果您深入研究一种方法,则可以看到其中涵盖的内容和未涵盖的内容,如下面的屏幕截图所示。
就个人而言,我发现报告的结构没有像为其他许多软件包生成的报告那样经过深思熟虑。 但是,您会得到相同的信息。
Ruby
接下来,让我们看一下Ruby。 对于Ruby,有SimpleCov 。 要引用软件包的存储库,它是…
…Ruby的代码覆盖率分析工具。 它使用Ruby的内置Coverage库来收集代码覆盖率数据,但是通过提供干净的API来过滤,分组,合并,格式化和显示这些结果,使处理结果更加容易,从而为您提供了一个完整的代码覆盖率套件只需设置几行代码即可。
考虑到它使用Ruby的内置Coverage库,该库可与许多Ruby测试包一起使用,包括Test :: Unit / Shoulda , Cucumber , Rails和RSpec 。
但是,据我所知,与其他所涵盖语言的代码覆盖率不同,Ruby的内置覆盖率库功能并不丰富。 但是,它仍然提供Line , Function , Method , Class , Branch和Path覆盖范围的分析。
第二,它不会像其他格式那样以XML格式输出报告。 但是,它同时支持HTML和JSON 。 但是,您很快就会看到,HTML报告几乎具有与其他报告一样丰富的功能,并且JSON格式既轻巧又可扫描。
安装及使用
与Ruby中的大多数库和软件包一样,SimpleCov易于安装。 为此,您只需将gem 'simplecov', :require => false, :group => :test
到您的Gemfile中,然后运行bundle install
。 要使用它,只需将以下两行添加到首选测试框架的配置文件中:
require 'simplecov'
SimpleCov.start
在开发本文的Ruby存储库的过程中,我将其与RSpec结合使用。 因此,我将其包含在RSpec生成的spec/spec_helper.rb
文件的顶部。
报告范例
在运行bundle exec rspec
或bin/rspec —init
,SimpleCov会生成一组报告(与其他coverage库非常相似),并将它们存储在项目的coverage
目录中。
您可以在上面的屏幕截图中看到,基于HTML的报告的输出与其他报告非常相似。 它列出了总体覆盖率水平,并显示了如何生成覆盖率百分比的细分。 对于报告中的每个文件,它都会列出其覆盖率,测试覆盖的行,未覆盖的行,等等。
同样,与其他HTML报表一样,您可以单击报表中的任何文件,以直观的方式查看测试覆盖了哪些行,而哪些行没有漏掉,或者用SimpleCov术语来说,漏掉了哪些行。
走
让我们看一下Go中的代码覆盖范围。 像Go中的许多内容一样,代码覆盖支持由其内置工具之一Go Cover本身提供。 作为Go 1.2的一部分发布,Cover工作于……
…在编译之前重写软件包的源代码,以添加工具,编译和运行修改后的源代码并转储统计信息。
Rob Pike在一篇有关Cover的出色文章中解释说,这是与许多报道工具所采用的方法不同的原因,因为…
…(标准方法)难以实施,因为对二进制执行的分析具有挑战性。 它还需要可靠的方式将执行跟踪绑定回源代码,这也可能很困难。 问题包括调试信息不正确,以及内联函数等使分析复杂化的问题。 最重要的是,这种方法是非常不可移植的。 由于调试支持在系统之间存在很大差异,因此需要针对每种体系结构以及在某种程度上针对每种操作系统重新进行此操作。
Cover以您期望的方式分析文件,并按Line , Function , Method , Class , Branch和Path覆盖范围进行分析。
安装及使用
由于Go Cover随Go 1.2一起提供,因此如果您安装了最新版本,它就已经可用。 要运行最基本的覆盖率分析,请在开发的程序包中运行以下命令:
go test -cover
对于为本文开发的示例Go存储库 ,它将以下输出呈现给STDOUT:
PASS
coverage: 100.0% of statements
ok github.com/settermjd/simple-entity 0.010s
您可以看到它具有100%的覆盖率。 增加复杂性,我们可以通过运行以下命令生成覆盖率配置文件:
go test -coverprofile=coverage.out
此命令生成收集的统计信息并将其存储在coverage.out
。 然后我们可以通过运行以下命令分析输出:
go tool cover -func=coverage.out
对于存储库中的代码,将生成以下输出:
github.com/settermjd/simple-entity/user.go:7: setName 100.0%
github.com/settermjd/simple-entity/user.go:11: getName 100.0%
total: (statements) 100.0%
在这里,您可以看到构成代码覆盖率的行和方法以及归因于它们的覆盖率的百分比。 最初打印到STDOUT时,该报告还可以通过运行以下命令以HTML格式获得:
go tool cover -html=coverage.out
您可以在下图中看到生成的报告。 与其他图书馆HTML报告一样,它显示的内容用绿色覆盖,而没有用红色覆盖。 布局略有不同,但最终结果是相同的。
结论
因此,这是对当今可用的五种最受欢迎的软件开发语言的代码覆盖范围的高级观察: Go , Python , Ruby , PHP和Java 。 无论是在分析的深度还是在报告功能上,某些库都具有比其他库更多的功能。 而且,有些比其他更容易入手。
但是,无论使用哪种语言进行开发,您都拥有足够多的代码覆盖支持来帮助您评估和提高测试质量。
我强烈建议您开始使用代码覆盖率分析(如果尚未开始的话),并将其集成到持续的集成和开发管道中。
您是否使用其他库? 是否有我未涵盖的功能? 在评论中分享您的反馈。
翻译自: https://www.javacodegeeks.com/2017/11/libraries-packages-code-coverage-ecosystem.html