Jacoco是Java Code Coverage的缩写,顾名思义,它是获取Java代码执行覆盖率的一个工具,通常用它来获取单元测试覆盖率。它通过分析Java字节码来得到代码执行覆盖率,因此它还可以分析任何基于JVM的语言(如Croovy、Kotlin)的覆盖率。本文不讨论如何用Jacoco获取单元测试的代码覆盖率,而是从Jacoco的原理出发,介绍如何通过Jacoco获取SIT或者UAT的测试覆盖率。更准确来讲,是获取一个应用执行过的代码占总代码的比率。包括字节码指令覆盖率,分支覆盖率,圈复杂度覆盖率,行覆盖率,方法覆盖率和类覆盖率。

Jacoco原理简介

Jacoco通过修改喂给JVM的字节码来达到获取那些代码执行了的目的。修改方式有两种,一种在线(on-the-fly),是通过Java agent,在JVM执行字节码之前动态对其进行修改,这种方式更灵活,也是Jcoco的一大特性。另一种是离线(offline)模式,在Java程序字节码文件(.class文件)生成之前进行修改,这样的字节码就不纯了。一般在无法使用on-the-fly方式的时候才使用offline方式。

上面这些概括起来讲,Jacoco最牛X的地方就在于它能够知道一个基于JVM的应用程序中哪些代码(指令、分支、行、方法、类)被执行了。用它除以总代码量,就得到了代码执行覆盖率。

由此,我们可以推断出Jacoco生成单元测试覆盖率报告的原理:单元测试代码会调用被测试代码,被测试代码的字节码指令会被Jacoco截获,用被截获的代码量除以总代码量,就算出了单元测试代码覆盖率。举一反三,在SIT或者UT的时候,也需要执行Java应用程序中的代码,因此可以也通过Jacoco获取被执行过的代码,从而计算出SIT,UT测试代码覆盖率。

使用Jacoco生成代码执行覆盖率报告

接下来通过一个实验介绍如何使用Jacoco获取一个Java web应用代码的执行率。就拿Tomcat自带的example应用来做实验,我们在启动Tomcat时带上Jacoco的Java agent;然后在页面上做一些点击操作,触发后台Java代码的执行;再抓取包含执行情况数据,放到.exec的二进制文件中;最后由这些二进制文件生成html格式的报告,验证被覆盖的代码是否和我们点击的内容相关。

下载Jacoco(https://www.jacoco.org),解压缩。

下载Tomcat(https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/ 清华mirror),然后解压缩,进入bin目录,找到catalina.bat文件(Windows)。

修改如下代码,让Tomcat在启动时带上Javacoco的agent。

set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"

修改为

set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS% -javaagent:C:\Users\Robot\Application\jacoco-0.8.5\lib\jacocoagent.jar=destfile=jacoco.exec,output=tcpserver"

其中指定了javaagent是C:\Users\Robot\Application\jacoco-0.8.5\lib\jacocoagent.jar,解压Jacoco可以得到;指定了output是tcpserver,也就是需要通过访问一个地址才能获取到数据。默认地址是本地IP地址,端口号是6300。其它参数说明见:https://www.jacoco.org/jacoco/trunk/doc/agent.html

设置完成之后,双击Tomcat bin目录下的startup.bat,启动Tomcat。控制台可以看见javaagent设置生效。此时Jacoco就可以动态地拦截喂给JVM的字节码,并且监听6300端口号和所以本机地址,等待获取代码执行情况数据(暂且称为.exec文件数据)的请求。

输入地址http://127.0.0.1:8080/ ,打开Tomcat 欢迎页面,做一些点击操作,可以确定它已经执行了一些字节码。

获取执行情况数据,在jacococli.jar所在目录(与jacocoagent.jar目录一致)执行命令:

java -jar jacococli.jar dump  --port  --destfile data/jacoco-it.exec

Jacoco会在当前目录下生成data/jacoco-it.exec文件,这个文件是一个二进制文件,我们无法直接查看它,需要用它生成html或者其它格式的文件。

执行如下命令生成html报告。--classfiles制定应用程序的class文件所在目录,--html指定html报告所在目录。

java -jar jacococli.jar report data/jacoco-it.exec --classfiles C:/Users/Robot/Application/apache-tomcat-9.0./webapps/examples/WEB-INF/classes --html html

打开html目录下的index.html文件就可以看到报告了。

小结

上面实验比较简单,只为辅助对Jacoco原理的理解。理解了原理之后,参照官网的手册就可以用Jacoco来做一些实用的操作,提高Java代码的质量。

使用Jacoco获取 Java 程序的代码执行覆盖率的更多相关文章

  1. Java 程序是如何执行的

    Java 程序是如何执行的 了解任何一门语言的精髓都是先俯览其全貌,从宏观的视角把握全局,然后再深入每个知识点逐个击破,这样就可以深入而快速的掌握一项技能.同样学习 Java 也是如此,本节就让我们先 ...

  2. 分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要)

    原文:分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要) Java InputStream读取数据问题 ======== ...

  3. 分享非常有用的Java程序(关键代码)(七)---抓屏程序

    原文:分享非常有用的Java程序(关键代码)(七)---抓屏程序 import java.awt.Dimension; import java.awt.Rectangle; import java.a ...

  4. 分享非常有用的Java程序 (关键代码)(六)---解析/读取XML 文件(重要)

    原文:分享非常有用的Java程序 (关键代码)(六)---解析/读取XML 文件(重要) XML文件 <?xml version="1.0"?> <student ...

  5. 分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map

    原文:分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map import java.util.Map; import org.apache.commons.lang.Ar ...

  6. 分享非常有用的Java程序 (关键代码)(四)---动态改变数组的大小

    原文:分享非常有用的Java程序 (关键代码)(四)---动态改变数组的大小 /** * Reallocates an array with a new size, and copies the co ...

  7. 分享非常有用的Java程序 (关键代码) (二)---列出文件和目录

    原文:分享非常有用的Java程序 (关键代码) (二)---列出文件和目录 File dir = new File("directoryName"); String[] child ...

  8. 分享非常有用的Java程序 (关键代码) (三)---创建ZIP和JAR文件

    原文:分享非常有用的Java程序 (关键代码) (三)---创建ZIP和JAR文件 import java.util.zip.*; import java.io.*; public class Zip ...

  9. 分享非常有用的Java程序 (关键代码) (一)

    原文:分享非常有用的Java程序 (关键代码) (一)   分享一些非常有用的Java程序 (关键代码) ,希望对你有所帮助. 1.  得到当前方法的名字 String methodName = Th ...

随机推荐

  1. java 不可变对象 final Collections guava 简单样例

    本地环境 jdk1.8 连接 Google Guava官方教程(中文版) journaldev 说明 java的final关键字大家都了解,但是final修饰的如果是引用类型,那么不可修改的其实只是重 ...

  2. 【7.9校内test】T2 极值问题

    这个题真的,毫无思路的说,但是我们会打表啊: lz的打表之路: 当然是手写一个暴力啦(*^▽^*)! 然后滚去配置lemon测试一下暴力可以得多少分qwq: 是的40分呢! 然后其实看上面也能看出来一 ...

  3. CodeForces-431D Random Task

    题目描述 求一个\(n\),使得\(n+1\)到\(2n\)这些数的二进制中恰好有\(k\)个\(1\)的数有\(m\)个. Input 输入包含两个正整数\(m,k\).$(0<=m<= ...

  4. 官宣!VS Code Python 全新功能在 PyCon China 全球首发!

    北京时间 2019 年 9 月 21 日,PyCon China 2019 在上海举行. 在下午的演讲中,来自微软开发工具事业部的资深研发工程师 在演讲中,我们看到了 Azure Notebook 与 ...

  5. JS 一位数左边补零

  6. Java 判断是否为回文字符串

    回文字符串有两种:abcba,abccba. 代码: static boolean func(String str) { int len = str.length(); for (int i = 0; ...

  7. Git入门指南九:远程仓库的使用【转】

    转自:http://blog.csdn.net/wirelessqa/article/details/20152651 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 十三 ...

  8. Qualcomm_Mobile_OpenCL.pdf 翻译-9-OpenCL优化用例的学习

    在这一章中,将会用一些例子来展示如何使用之前章节中讨论的技术来进行优化.除了一些小的简单代码片段的展示外,还有两个熟知的图像滤波处理,Epsilon滤波和Sobel滤波,将会使用之前章节中讨论的方法进 ...

  9. 为什么 Android 开发者都应该尝试一下 Anko?

    简评: 这里介绍的仅仅是 Anko 中很小的一部分,Kotlin + Anko 真的让 Android 开发简化了不少,用了 Anko 基本就可以告别那些什么 Android 不得不知的代码收集贴了. ...

  10. Linux日常之命令uniq

    命令uniq 作用是过滤文件内容重复部分 需要注意的是,该命令只是对相邻的行进行比较,若两个相同的行不相邻,不会被过滤掉 选项 -c,在每行行首显示出该行出现的次数 -d,只显示出重复的行 -u,只显 ...