前言:
本文主要介绍Jacoco集成jenkins+sonar对Java接口覆盖率进行统计。
主流的代码覆盖率的工具有四种,Clover适用于商用,暂不提,Jacoco、Emma、Cobertura主要参数对比请见下表:
工作流程 :
1、对Java字节码进行插桩,支持On-The-Fly和Offine两种方式。
2、执行测试用例,收集程序执行轨迹信息,将其dump到内存。
3、数据处理器结合程序执行轨迹信息和代码结构信息分析生成代码覆盖率报告。
4、将代码覆盖率报告图形化展示出来,如html、xml等文件格式。
Jacoco 是一个开源的覆盖率工具,可以嵌入到 Ant 、Maven 中,并提供了 EclEmma Eclipse 插件,可以使用 Java Agent 技术对Java程序进行监控。很多第三方的工具提供了对 Jacoco 的集成,如:Sonar、Jenkins、IDEA。原理和介绍可参考文章:jacoco统计Android代码覆盖率。
一、jacoco统计【一起剧本杀】接口覆盖率
1、下载项目源码到本地:
2、下载jacoco:https://www.eclemma.org/jacoco/,解压。
3、下载ant:http://ant.apache.org/,解压,配置环境变量。
4、进入ant中bin目录下对build.xml进行编辑。
<?xml version="1.0" encoding="UTF-8"?>
<project name="test" xmlns:jacoco="antlib:org.jacoco.ant" >
<!--Jacoco的安装路径-->
<property name="jacocoantPath" value="E:\finalJacoco\lib\jacocoant.jar"/>
<!--最终生成.exec文件的路径,Jacoco就是根据这个文件生成最终的报告的-->
<property name="jacocoexecPath" value="E:\jenkins\workspace\yokaJacoco\jacoco.exec"/>
<!--<property name="jacocoexecPath" value="E:\finalJacoco\target\jacoco.exec"/>-->
<!--生成覆盖率报告的路径-->
<property name="reportfolderPath" value="E:\finalJacoco\report"/>
<!--远程tomcat服务的ip地址-->
<property name="server_ip" value="10.225.10.102"/>
<!--前面配置的远程tomcat服务打开的端口,要跟上面配置的一样-->
<property name="server_port" value="6300"/>
<!--源代码路径可以包含多个源代码-->
<property name="webSrcpath" value="E:\YOKAJacoco\murder-master-master-af65d011498b5a66c95735911471f55872b53d6e\src\main\java" />
<!--.class文件路径可以包含多个-->
<property name="webClasspath" value="E:\YOKAJacoco\murder-master-master-af65d011498b5a66c95735911471f55872b53d6e\target\classes"/>
<!--让ant知道去哪儿找Jacoco-->
<taskdef uri="antlib:org.jacoco.ant" resource="org/jacoco/ant/antlib.xml">
<classpath path="${jacocoantPath}" />
</taskdef>
<target name="merge">
<jacoco:merge destfile="${allJacocoexecPath}">
<fileset dir="${baseDir}" includes="*.exec"/>
</jacoco:merge>
</target>
<!--dump任务:
根据前面配置的ip地址,和端口号,
访问目标tomcat服务,并生成.exec文件。-->
<target name="dump">
<jacoco:dump address="${server_ip}" reset="true" destfile="${jacocoexecPath}" port="${server_port}" append="false"/>
</target>
<!--jacoco任务:
根据前面配置的源代码路径和.class文件路径,
根据dump后,生成的.exec文件,生成最终的html覆盖率报告。-->
<target name="report">
<delete dir="${reportfolderPath}" />
<mkdir dir="${reportfolderPath}" />
<jacoco:report>
<executiondata>
<file file="${jacocoexecPath}" />
</executiondata>
<structure name="JaCoCo Report">
<group name="Launch related">
<!--此处配置classes文件地址 -->
<classfiles>
<fileset dir="${webClasspath}" />
</classfiles>
<!--此处配置源码地址-->
<sourcefiles encoding="utf-8">
<fileset dir="${webSrcpath}" />
</sourcefiles>
</group>
</structure>
<html destdir="${reportfolderPath}" encoding="utf-8" />
</jacoco:report>
</target>
</project>
注: 1、jacocoexecPath:生成.exec的路径
2、reportfolderPath:生成覆盖率报告的路径
3、server_ip:远程服务的ip,因为部署在本地,这里取本机ip
4、server_port:远程服务的端口,可自行取值,非项目配置的端口号。
5、webSrcpath:源代码路径
6、webClasspath:.class文件路径
5、通过jacocoagent启动项目(jacoco会在编译生成的class文件中进行插桩)
5.1 通过maven打包,点击package
5.2 在项目target目录下会生成项目jar包:
5.3 在项目终端输入启动命令:
java -javaagent:E:\finalJacoco\lib\jacocoagent.jar=destfile=
E:\jenkins\workspace\yokaJacoco\jacoco.exec,includes=*,output=tcpserver,port=6300,address=10.225.10.102 -jar E:\YOKAJacoco\murder-master
-master-af65d011498b5a66c95735911471f55872b53d6e\target\murder-master-0.0.1-SNAPSHOT.jar
注: 1、修改jacocoagent.jar的具体目录
2、修改jacoco.exec的具体目录
3、修改服务启动的ip和端口号
4、修改项目jar包的路径
6、访问接口:http://localhost:8099/api/version/getLatestVersion ,访问成功。
7、进入Ant目录下:
7.1 输入命令:ant dump 生成jacoco.exec文件
7.2 输入命令:ant report 生成报告文件
8、找到项目下的index.html文件,查看报告结果
二、jacoco集成jenkins
1、下载jenkins:https://www.jenkins.io/zh/download/ 配置账号密码。
2、打开 Jenkins →系统管理 → 管理插件 → 可选插件 → 安装 JaCoCo plugin
3、jenkins新建一个job
3.1 进入配置文件 →Add build step
3.2 添加:Execute Windows batch command,输入Command:
3.3 添加:Add post-build action → Record JaCoCo coverage report
三、jacoco集成Sonar
1、sonar原理:
1.1 Sonanqube-scanner:负责搜集代码相关数据,存入mysql
1.2 SonarQube: 负责对搜集的数据进行分析 ELastic Search搜索服务器,通过不同的插件算法来对这些结果再加工,最终以量化的方式来衡量代码质量,最终展示给用户AST抽象语法树(Abstract Syntax Tree)。
2、sonar简介:一个开源的静态代码扫描(Sonar Scanner)和度量的平台,通过插件形式,可以支持多种语言的质量管理和检测,自定义扫描规则(插件形式)。
3、下载sonarqube:https://www.sonarqube.org/downloads/
注:建议下载社区版且版本号低于8.0
4、新建sonar数据库和用户,并赋予权限
4.1 创建数据库: CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci;
4.2 创建用户: CREATE USER ‘sonar’ IDENTIFIED BY ‘sonar’;
4.3 配置用户的权限 GRANT ALL ON sonar.* TO ‘sonar’@’%’ IDENTIFIED BY ‘sonar’; GRANT ALL ON sonar.* TO ‘sonar’@‘localhost’ IDENTIFIED BY ‘sonar’;
4.4 更新权限:flush privileges;
注:1、由于需要root权限去新建用户并赋予权限,本次操作是下载mysql到本地。
2、建议mysql版本为大于等于5.6小于8.0。
5、修改SonarQube配置文件(账号,密码,url)
# The schema must be created first.
sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
#----- Embedded Database (default)
# H2 embedded database server listening port, defaults to 9092
#sonar.embeddedDatabase.port=9092
#----- DEPRECATED
#----- MySQL >=5.6 && <8.0
# Support of MySQL is dropped in Data Center Editions and deprecated in all other editions
# Only InnoDB storage engine is supported (not myISAM).
# Only the bundled driver is supported. It can not be changed.
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
6、下载SonarQube Scanner:https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner,解压。
6.1 配置文件:sonar-scanner.properties
#----- Default SonarQube server
sonar.host.url=http://localhost:9000
#----- Default source code encoding
sonar.sourceEncoding=UTF-8
sonar.jdbc.username=root
sonar.jdbc.password=
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?
useUnicode=true&characterEncoding=utf8
&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
6.2 项目根目录新建:sonar-project.properties
# 指定SonarQube instance必须是唯一的
sonar.projectKey=yoka
# 设置SonarQube UI显示的名称
# PS:有人会问这里的名称是否可以是中文名称,我在网上搜索了好多资料都说是不可以的(至少我看到的资料都是)
# 后来自己尝试了一下,答案是可以写成中文的,但是要换一种方式,比如你想把项目名称命名为“测试”,
# 那么在这里就要写成“\u6d4b\u8bd5”,那么下面这个参数就应该这样写“sonar.projectName= \u6d4b\u8bd5”,
# 说白了就是将中文转成Unicode
sonar.projectName=yoka
sonar.projectVersion=1.0
sonar.language=java
# 指定src和classes文件夹位置,当然也可以是全路径,如果是当前工程根目录下用“.”表示也可以,比如“sonar.sources=.”
sonar.sources=E:\\YOKAJacoco\\murder-master-master-af65d011498b5a66c95735911471f55872b53d6e\\src
sonar.java.binaries=E:\\YOKAJacoco\\murder-master-master-af65d011498b5a66c95735911471f55872b53d6e\\target\\classes
# 下面的这两个参数作用是相同的,因为有时我们需要指定某个文件夹或者忽略某个文件夹
# sonar.inclusions=src1/**,src3/**
# sonar.exclusions=src2/**,src4/**
# 源码编码,默认是系统编码
sonar.sourceEncoding=UTF-8
# Set jacoco Configuration
# 指定代码覆盖率工具
sonar.core.codeCoveragePlugin=jacoco
# 指定exec二进制文件存放路径
sonar.jacoco.reportPaths=E:\\jenkins\\workspace\\yokaJacoco\\jacoco.exec
# 以下属性可选择性加,当然也可以不加
sonar.dynamicAnalysis=reuseReports
sonar.jacoco.reportMissing.force.zero=false
7、运行SonarQube:
7.1 进入SonarQube的bin目录下,点击:StartSonar.bat
7.2 访问url:http://localhost:9000
注:默认账号密码:admin admin
四、 jenkins集成Sonar
1、打开 Jenkins →系统管理 → 管理插件 → 可选插件 → 安装 SonarQube
2、配置证书
2.1 获取token
2.2 访问url:http://localhost:9000/account/security/
2.3 在Generate Tokens输入项目名,点击按钮【Generate】
2.4 复制生成的token
3、进入Jenkins →凭据 →系统 →全局凭据 (unrestricted) →Secret text:输入token,保存。
4、进入Jenkins →configuration,配置SonarQube servers:
5、进入job的配置文件
5.1 Add build step →Execute SonarQube Scanner
5.2 配置JDK版本
5.3 配置Analysis properties
sonar.projectKey=yoka
sonar.projectName=yoka
sonar.projectVersion=0.0.1-SNAPSHOT
sonar.language=java
sonar.sources=E:\\YOKAJacoco\\murder-master-master-af65d011498b5a66c95735911471f55872b53d6e\\src
sonar.java.binaries=E:\\YOKAJacoco\\murder-master-master-af65d011498b5a66c95735911471f55872b53d6e\\target\\classes
sonar.sourceEncoding=UTF-8
sonar.login=admin
sonar.password=admin
五、发送邮件
1、打开 Jenkins →系统管理 → 管理插件 → 可选插件 → 安装 Extended E-mail
2、Jenkins →configuration →配置Extended E-mail Notification和E-mail Notification
3、进入job添加 Editable Email Notification
4、编写:Default Content
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>代码覆盖率报告</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
offset="0" >
<div align="center">
<table width="95%" cellpadding="0" cellspacing="0"
style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<br /><td><b><font color="#0B610B">(本邮件是程序自动下发的,请勿回复!)</b></td>
</tr>
<tr>
<td><h2>
<br /><font color="#0000FF">构建结果 - Successful</font>
</h2></td>
</tr>
<tr>
<td><br />
<b><font color="#0B610B">构建信息:</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<li>项目名称 : 一起剧本杀</li><br>
<li>jenkins测试报告地址 : <a href="http://localhost:8080/job/yokaJacoco">http://localhost:8080/job/yokaJacoco</a></li><br>
<li>sonarqube测试报告 : <a href="http://localhost:9000/dashboard?id=yoka">http://localhost:9000/dashboard?id=yoka</a></li><br>
</ul>
</td>
</tr>
<tr>
<td><br />
<b><font color="#0B610B">基础分析:</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<li>行覆盖率:度量被测程序的每行代码是否被执行,判断标准行中是否至少有一个指令被执行。</li><br>
<li>类覆盖率:度量计算class类文件是否被执行。</li><br>
<li>分支覆盖率:度量if和switch语句的分支覆盖情况,计算一个方法里面的总分支数,确定执行和不执行的 分支数量。</li><br>
<li>方法覆盖率:度量被测程序的方法执行情况,是否执行取决于方法中是否有至少一个指令被执行。</li><br>
<li>指令覆盖:计数单元是单个java二进制代码指令,指令覆盖率提供了代码是否被执行的信息,度量完全 独立源码格式。</li><br>
<li>圈复杂度:在(线性)组合中,计算在一个方法里面所有可能路径的最小数目,缺失的复杂度同样表示测 试案例没有完全覆盖到这个模块。</li><br>
</ul>
</td>
</tr>
<tr>
<td><br />
<b><font color="#0B610B">jacoco流程解析:</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<li>对Java字节码进行插桩,支持On-The-Fly和Offine两种方式。</li><br>
<li>执行测试用例,收集程序执行轨迹信息,将其dump到内存。</li><br>
<li>数据处理器结合程序执行轨迹信息和代码结构信息分析生成代码覆盖率报告。</li><br>
<li>将代码覆盖率报告图形化展示出来,如html、xml等文件格式。</li><br>
</ul>
</td>
</tr>
</table>
</div>
</body>
</html>
5、构建后收到邮件
六、运行接口自动化脚本,生成报告
1、触发【一起剧本杀】接口自动化python脚本:
2、构建 jenkins job
3、生成接口覆盖率报告
- jenkins
- sonar
七、总结
文章介绍了Jacoco统计Java接口覆盖率主要流程,由于篇幅原因,有些细节和原理没有详细说明,且操作中踩坑比较多。
jacoco可做的仍然有很多:增量覆盖率,全量覆盖率,根据业务需求进行二次开发…希望有兴趣或者有经验的同学一起沟通。