了解Jacoco
Jacoco是由Eclipse发行,用于计算Java代码覆盖率的免费开源工具包。Eclipse EclEmma在2.0版本之前集成的是EclEmma团队基于EMMA开发的代码覆盖工具,之后的版本都是基于Jacoco的。
产品定义
- 特征
指令(C0),分支(C1),行,方法,类型和圈复杂度的覆盖率分析。
基于Java字节码,因此无需源文件也可以工作。
通过基于Java的即时工具进行简单集成。
其他集成方案(例如自定义类加载器)也可以通过API来实现。
与框架无关的:与基于Java VM的应用程序(如纯Java程序,OSGi框架,Web容器或EJB服务器)平滑集成。
与所有已发布的Java类文件版本兼容。
支持不同的 JVM语言。
几种报告格式(HTML,XML,CSV)。
远程协议和JMX控制可在任何时间点从coverage代理请求执行数据转储。
支持Ant任务收集和管理执行数据并创建结构化的覆盖率报告。
支持Maven插件收集覆盖率信息并在Maven构建中创建报告。 - 非功能特性
简单的用法以及与现有构建脚本和工具的集成。
良好的性能和最小的运行时开销,尤其是对于大型项目。
轻量级实现,对外部库和系统资源的依赖性最小。
完善的 JavaDoc文档 和 与其他工具集成的demo。
回归测试全功能测试覆盖率基于 JUnit的测试用例。
下面举例简单介绍一些其他的免费Java代码覆盖率工具
工具 | 介绍 | 覆盖类型 | 结果统计 |
EMMA | 基于Java字节码检测的Java覆盖工具,速度快,因无更新eclipse已废弃 | 类,方法,行,基本块 | 支持在<方法,类,行,基本块,包和所有类>级别汇总;报告支持纯文本,HTML,XML |
Jcov | 基于Java字节码检测的开源Java覆盖工具,有动态和静态两种方式,现用于OpenJdk中 | 基本块,方法,分支,行 | 基于测试套件生成单个报告,可合并,报告支持HTML,XML |
Serenity | 自动化验收测试工具,除了基于Java字节码检测的代码覆盖,还支持代码度量–圈复杂度,稳定性等 | 基本块,方法,分支,行 | 报告结果可通过Jenkins或ide展示 |
Cobertura | 基于Java字节码检测的开源Java覆盖工具 | 类,行,分支 | 报告支持HTML,XML |
虽然有很多的工具,也是大同小异了,但我们大都最终选择Jacoco,简单易用并且轻量级肯定是首要原因,维护也比较积极。但每个工具都有自己的坑,等待我们去跳去吐槽~
Gradle Jacoco Plugin 使用
1. 引入Jacoco插件
直接在需要覆盖率的项目(project)中引用即可
apply plugin: 'jacoco'
Note:
- 项目中引入插件后,一个新的名为
jacocoTestReport
的任务会默认存在。 - 在执行测试文件后要手动执行任务
jacocoTestReport
,因为任务jacocoTestReport
不依赖于任务test
。另一种方式就是重写任务jacocoTestReport
,让其依赖于任务test
。 - 默认生成的是HTML的报告,默认路径
$buildDir/reports/jacoco/test
。
2. 配置Jacoco插件
以下是Jacoco插件提供的拓展任务(type为JacocoPluginExtension),可以让我们使用其提供的默认值配置,我们也可以根据自身情况覆盖其中的一些属性。
jacoco {
toolVersion = "0.8.5"
reportsDir = file("$buildDir/customJacocoReportDir")
}
toolVersion不填,会取当前插件的默认jacoco版本,试了下在grade4.8下取的是 jacoco 0.8.0 版本的jar。
reportsDir不填,会取默认路径$buildDir/reports/jacoco
。
3. 配置Jacoco报告参数
以下的jacocoTestReport
是默认存在的类型为JacocoReport
的任务,可以用于生成不同格式的代码覆盖率报告,默认生成任务所在模块的代码覆盖率。
如果想要有定制化需求,可建个新的类型为JacocoReport
任务使用。
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
// 报告的生成位置
html.destination file("${buildDir}/jacocoHtml")
}
}
以上配置好就可以在报告生成路径(${buildDir}/jacocoHtml)下看到报告啦,以下为html的报告图示
4. 覆盖率合并计算–JacocoMerge(合并报告)
可以通过下图了解下这几个Jacoco插件Task的组成。Reporting 和 ReportContainer 是gradle提供的覆盖率报告接口,其他覆盖率工具应该也是通过此接口来实现功能,JacocoReport和JacocoReportsContainer 分别实现了这两个接口,JacocoMerge是Jacoco插件单独提供的功能。
多模块项目,或者一个项目中有多个Test
任务,会生成多个exec文件(exec文件会以Test任务的名字命名),我们如果想要合并它们,就可以用JacocoMerge。
创建一个type为jacocoMerge
的任务,这个任务需要我们手动执行,一般会让JacocoReport
依赖其执行,而且要让Test
任务先于其执行。总结来说它们的执行顺序从先到后为:Test > JacocoMerge > JacocoReport 。
以下为JacocoMerge的示例,JacocoMerge
的executionData
:待合并的exec文件列表,JacocoMerge
的destinationFile
:要写入合并的exec数据的文件,JacocoReport
的executionData
:指定报告要分析的exec数据文件路径。注意executionData = xxx
的这种写法是set(直接覆盖原值),executionData xxx
的这种写法是在原值基础上追加文件。
task jacocoMerge(type: JacocoMerge, dependsOn: [testTask1, testTask2]) {
File jacocoFile = file("$buildDir/jacoco/jacoco.exec")
// 删除上一次生成的合并文件jacoco.exec
doFirst {
jacocoFile.delete()
}
// 待合并列表加入当前模块下的exec文件
executionData files {
file("$buildDir/jacoco").listFiles()
}
// 待合并列表加入另一个模块services生成的exec文件
executionData files {
file(project(":services").buildDir.path + "/jacoco").listFiles()
}
destinationFile = jacocoFile
}
// 在 3 步骤上进行补充配置
jacocoTestReport(dependsOn: jacocoMerge) {
// 指定上面jacocoMerge生成合并后的exec文件(不指定的话会默认取$buildDir/jacoco/test.exec)
executionData = "$buildDir/jacoco/jacoco.exec"
// 添加service模块的源码进入覆盖率报告
sourceSets project(":services").sourceSets.main
reports {
xml.enabled false
csv.enabled false
html.enabled true
}
}
Jenkins Jacoco Plugin 使用
安装
Jenkins安装Jacoco插件
使用
Jenkins Jacoco插件可以作为构建后步骤中的一部分,通过build项目生成的exec文件,来记录并展示覆盖率数据,还可以在项目主页面上以图表的方式展示覆盖率趋势。
覆盖率报告配置
要启用Jacoco插件,只需要在构建后步骤(Post-build Actions)中添加一项Record Jacoco coverage report,Jenkins Jacoco覆盖率报告配置即可。
配置说明
- exec配置
Path to exec files(e.g.: **/target/**.exec, **/jacoco.exec)
: 填入构建项目时Jacoco生成的exec文件(本文示例填:在上面提到过的合并后的jacoco.exec) - class配置(算入覆盖率的class文件)
Inclusions (e.g.: **/*.class)
: 要计算覆盖率的class文件。Exclusions (e.g.: **/*Test*.class)
: 排除不需要计算覆盖率的class文件。Path to class directories (e.g.: **/target/classDir, **/classes)
: 要计算覆盖率的class目录,即源码编译后生成的目录 - source配置(用于查看源码文件详细覆盖率)
Path to source directories (e.g.: **/mySourceFiles)
: 要查看覆盖率的源码目录。Inclusions (e.g.: **/*.java,**/*.groovy,**/*.gs)
: 指明要查看覆盖率的源码文件。Exclusions (e.g.: generated/**/*.java)
: 排除不需要查看覆盖率的源码文件。Disable display of source files for coverage
: 不展示源码覆盖率。选中此选项会让source配置失效。 - 根据阈值更改构建状态
Change build status according the thresholds
: 大于晴天行(第一行)的值则构建状态为success;位于晴天行(第一行)和雷雨天行(第二行)之间的值则构建状态为unstable;小于雷雨天行(第二行)的值则构建状态为fail。可选是否激活此功能。 - 覆盖率降低的值超过增量阈值则构建失败
Fail the build if coverage degrades more than the delta thresholds
: 覆盖率波动值低于所填值则构建状态为fail。可选是否激活此功能。
运行项目
配置好后启动项目,就可以在控制台(Console Output)中看到Jacoco Plugin的执行输出。
[JaCoCo plugin] Collecting JaCoCo coverage data...
[JaCoCo plugin] **/jacoco.exec;**/build/classes;**/src/main/java; locations are configured
[JaCoCo plugin] Number of found exec files for pattern **/jacoco.exec: 1
[JaCoCo plugin] Saving matched execfiles: /var/jenkins_home/workspace/test2/api/build/jacoco/jacoco.exec
[JaCoCo plugin] Saving matched class directories for class-pattern: **/build/classes:
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/api/build/classes 24 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/common/build/classes 5 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/model/build/classes 39 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/services/build/classes 88 files
[JaCoCo plugin] Saving matched source directories for source-pattern: **/src/main/java:
[JaCoCo plugin] Source Inclusions: **/*.java
[JaCoCo plugin] Source Exclusions:
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/admin/src/main/java 25 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/api/src/main/java 14 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/common/src/main/java 5 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/contract/src/main/java 29 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/model/src/main/java 19 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/sdk/src/main/java 3 files
[JaCoCo plugin] - /var/jenkins_home/workspace/test2/services/src/main/java 59 files
[JaCoCo plugin] Loading inclusions files..
[JaCoCo plugin] inclusions: [**/*.class]
[JaCoCo plugin] exclusions: [**/com/xingren/*/model/**, **/test/**/**Test.class]
[JaCoCo plugin] Thresholds: JacocoHealthReportThresholds [minClass=0, maxClass=0, minMethod=0, maxMethod=0, minLine=0, maxLine=0, minBranch=0, maxBranch=0, minInstruction=0, maxInstruction=0, minComplexity=0, maxComplexity=0]
[JaCoCo plugin] Publishing the results..
[JaCoCo plugin] Loading packages..
[JaCoCo plugin] Done.
[JaCoCo plugin] Overall coverage: class: 89, method: 71, line: 78, branch: 60, instruction: 73
Finished: SUCCESS
查看结果
添加了覆盖率配置构建后,在项目主页上会有一个图表展示。可以点击进去看具体源代码覆盖率。
在Jenkins项目列表页可通过编辑视图去配置 分支和行覆盖率 的显示。这两列数据的显示颜色会根据覆盖率的数值变化。