本文首发于: Jenkins 中文社区
对于 JaCoCo,有所了解但又不是很熟悉。 "有所了解"指的是在 CI 实践中已经使用 JaCoCo 对单元测试代码覆盖率统计: 当代码 push 到代码仓库后,用 JaCoCo 进行单元测试代码覆盖率统计,并将相应数据推送到 SonarQube。 "不是很熟"指的是应用场景也仅限于此,并未进行过多研究与实践。
前不久,有测试同事提出,想要在实际测试时,用 JaCoCo 统计功能测试代码覆盖率。 其主要目的是在经过功能测试后,通过查看代码覆盖率统计的相关指标,增强对软件质量的信心。 经查阅资料,证明这是可行的。
由于对 JaCoCo 不甚了解,于是查阅官网资料对 JaCoCo 进一步了解。
JaCoCo ,即 Java Code Coverage,是一款开源的 Java 代码覆盖率统计工具。 它由 EclEmma 团队根据多年来使用和集成现有库的经验教训而创建。
JaCoCo 应该为基于 Java VM 的环境中的代码覆盖率分析提供标准技术。 重点是提供一个轻量级的、灵活的、文档良好的库,以便与各种构建和开发工具集成。
对 JaCoCo 可以与现有构建脚本和工具进行集成这里做进一步说明: 官方提供了 Java API、Java Agent 、CLI、Ant 、Maven、Eclipse 这几种集成方式; 第三方提供了诸如与 Gradle、IDEA、Jenkins 等其它工具的集成方式。
JaCoCo 不仅支持统计本地服务的代码覆盖率,也支持统计远程服务的代码覆盖率。 单元测试覆盖率统计就是统计本地服务的代码覆盖率,代码和运行的服务在一台机器上,笔者这里通过使用 JaCoCo Maven 插件完成的。 而功能测试代码覆盖率统计则是统计远程服务的代码覆盖率,代码和运行的服务一般不在一台机器上,这里需要借助 JaCoCo Java agent 实现。
备注:实际上,JaCoCo Maven 插件也使用了 JaCoCo Java agent,不过用户不需要直接关系 Java agent 及其选项,Maven 插件都透明地处理了。
可以从 JaCoCo 官网 下载分发包,也可以从 Maven 仓库(中央仓库或私服)下载。 分发包的 lib 目录下,包括以下库:
需要将 jacocoagent.jar 推送到部署应用的服务器上,笔者这里用 Ansible 进行了批量推送。 Java 应用启动脚本需要加入类似下面的 JVM 参数:
JAVA_OPTS="$JAVA_OPTS -javaagent:/path/jacocoagent.jar=includes=*,output=tcpserver,append=false,address=$IP,port=$JACOCO_PORT"
这样在应用成功启动后,会暴露一个 TCP 服务,客户端可以连接到这个服务并获取执行数据文件。
相关属性说明如下:
Jenkins 任务大致有几个步骤:拉取代码,构建,dump 应用执行数据( jacoco.exec ),解析 JaCoCo 产生的 jacoco.exec 文件,然后生成覆盖率报告(HTML 格式)。 拉取代码这里无需多说,配置下从代码仓库(SVN/Git)和分支地址就可以了,比较简单。 构建这里用了 Jenkins Pipeline Maven Integration Plugin ,笔者这里所用的 Maven 命令是 mvn clean package -Dmaven.test.skip=true 。 dump 应用执行数据这里有多种方式:Ant、CLI、Maven,因为Java 应用是用 Maven 构建的,这里选择了 Maven Jacoco Plugin。 解析 JaCoCo 产生的 jacoco.exec 文件,然后生成覆盖率报告(HTML 格式)笔者这里使用了 Jenkins Jacoco Plugin。
Jenkins Pipeline 案例如下:
pipeline { agent any tools { jdk 'JDK1.8' } stages { stage('Checkout'){ steps{ git branch: '${GIT_BRANCH}', credentialsId: 'xxx-xxx-xx-xx-xxx', url: '${GIT_URL}' } } stage('Build') { steps{ withMaven(maven: 'maven'){ sh "mvn clean package -Dmaven.test.skip=true" } } } stage('DumpFromServer'){ steps { withMaven(maven: 'maven'){ sh 'mvn org.jacoco:jacoco-maven-plugin:0.8.4:dump -Djacoco.address=${SERVER_IP} -Djacoco.port=${JACOCO_PORT}' } } } stage('JacocoPublisher') { steps { jacoco() } } } }
JaCoCo 覆盖率报告,部分截图如下:
笔者所实现的方式并未覆盖任何场景,但是大同小异,相关工具的使用详情可以查看官网文档,因为它是最全面的。 笔者希望这个实践能给有类似诉求的同行一些参考,当然笔者也希望能够和大家互相交流。 同时笔者的 JaCoCo 实践之路并未结束,可能在使用的过程中会有一些问题需要解决, 后续也将考虑使用 Jenkins API 为需要统计功能测试代码覆盖率的 Java 应用实例自动生成一个对应的 Jenkins 任务, 并在 Java 应用实例销毁后,对相应的 Jenkins 任务进行清理等其它功能。
作者:王冬辉