JAVA代码覆盖率工具JaCoCo-原理篇
JAVA代码覆盖率工具JaCoCo-原理篇
1.2 JAVA覆盖率工具介绍
1.3.3 Apache Maven方式
1.3.4 Eclipse EclDmma Plugin方式
JAVA代码覆盖率工具JaCoCo-实践篇
一、覆盖率项目中使用介绍
1.5执行测试,收集覆盖率结果文件
1.5.1AndroidManifest文件的修改
1.5.2生成覆盖率的apk工具和jacoco-cov-sdk.jar包
二、覆盖率与BVT测试结合
2.1在BVT用例框架中插入覆盖率方法
2.2执行BVT用例,得到覆盖率
2.3批量生成覆盖率报告,解析入库
2.4分析覆盖率结果,得出用例和代码映射关系
三、差异覆盖率和全量覆盖率
JAVA代码覆盖率工具JaCoCo-踩坑篇
1.1 覆盖率包在部分手机6.0上安装失败
1.2 覆盖率包在部分4.X版本手机上生成ec文件失败
1.3 覆盖率报告生成后看不到源码覆盖情况
二、覆盖率一些需要注意的地方
JAVA代码覆盖率工具JaCoCo-原理篇
1.1 覆盖率定义
作为一个测试人员,保证产品的软件质量是其工作首要目标,为了这个目标,测试人员常常会通过很多手段或工具来加以保证,覆盖率就是其中一环比较重要的环节。
我们通常会将测试覆盖率分为两个部分,即“需求覆盖率”和“代码覆盖率”。
需求覆盖:指的是测试人员对需求的了解程度,根据需求的可测试性来拆分成各个子需求点,来编写相应的测试用例,最终建立一个需求和用例的映射关系,以用例的测试结果来验证需求的实现,可以理解为黑盒覆盖。
代码覆盖:为了更加全面的覆盖,我们可能还需要理解被测程序的逻辑,需要考虑到每个函数的输入与输出,逻辑分支代码的执行情况,这个时候我们的测试执行情况就以代码覆盖率来衡量,可以理解为白盒覆盖。
以上两者完全可以相辅相成,用代码覆盖结果反向的检查需求覆盖(用例)的测试是否充分完整。
如果做覆盖率测试?我们可以借助一些网上流行的各种覆盖率工具,本章主要介绍JaCoCo这个工具。
1.2 JAVA覆盖率工具介绍
市场上java主要代码覆盖率工具:EMMA、JaCoCo
总结一下个人对JaCoCo优势的理解:
(1)JaCoCo支持分支覆盖、引入了Agent模式。
(2)EMMA官网已经不维护了,JaCoCo是其团队开发的,可以理解为一个升级版。
(3)JaCoCo社区比较活跃,官网也在不断的维护更新。
我们前期使用的EMMA,也做了全量、差异覆盖率,和精准耦合也结合在了一起,但后来考虑到JaCoCo的优势,也就全部切换了过来。
1.2.1 JaCoCo简述
JaCoCo是一个开源的覆盖率工具(官网地址: http://www.eclemma.org/JaCoCo/ ),它针对的开发语言是java,其使用方法很灵活,可以嵌入到Ant、Maven中;可以作为Eclipse插件,可以使用其JavaAgent技术监控Java程序等等。
很多第三方的工具提供了对JaCoCo的集成,如sonar、Jenkins等。
JaCoCo包含了多种尺度的覆盖率计数器,包含指令级覆盖(Instructions,C0coverage),分支(Branches,C1coverage)、圈复杂度(CyclomaticComplexity)、行覆盖(Lines)、方法覆盖(non-abstract methods)、类覆盖(classes),后面会一一介绍。
我们先看看其覆盖率结果展现如下图1-1所示,方便读者先有一个大概的了解。

图1-1 覆盖率报告结果部分截图
标示绿色的为行覆盖充分,标红色的为未覆盖的行,黄色菱形的为分支部分覆盖,绿色菱形为分支完全覆盖。
通过这个报告的结果就可以知道代码真实的执行情况,便于我们分析评估结果。
1.2.2 JaCoCo基本概念
行覆盖率:度量被测程序的每行代码是否被执行,判断标准行中是否至少有一个指令被执行。
类覆盖率:度量计算class类文件是否被执行。
分支覆盖率:度量if和switch语句的分支覆盖情况,计算一个方法里面的总分支数,确定执行和不执行的 分支数量。
方法覆盖率:度量被测程序的方法执行情况,是否执行取决于方法中是否有至少一个指令被执行。
指令覆盖:计数单元是单个java二进制代码指令,指令覆盖率提供了代码是否被执行的信息,度量完全 独立源码格式。
圈复杂度:在(线性)组合中,计算在一个方法里面所有可能路径的最小数目,缺失的复杂度同样表示测 试案例没有完全覆盖到这个模块。
1.2.3 JaCoCo 原理
1.注入方式介绍

这个图包含了几种不同的收集覆盖率信息的方法,每种方法的实现方法都不一样,带颜色的部分是JaCoCo比较有特色的地方。
上面各个名次含义(带颜色的为JaCoCo支持):

上表JaCoCo支持的部分,再详细的解释下:
(1)JaCoCo在Byte Code时使用的ASM技术修改字节码方法,可以修改Jar文件、class文件字节码文件。
(2)JaCoCo同时支持on-the-fly和offline的两种插桩模式。
On-the-fly插桩:
JVM中通过-javaagent参数指定特定的jar文件启动Instrumentation的代理程序,代理程序在通过Class Loader装载一个class前判断是否转换修改class文件,将统计代码插入class,测试覆盖率分析可以在JVM执行测试代码的过程中完成。
Offline模式:
在测试前先对文件进行插桩,然后生成插过桩的class或jar包,测试插过桩 的class和jar包后,会生成动态覆盖信息到文件,最后统一对覆盖信息进行处理,并生成报告。
On-the-fly和offline比较:
On-the-fly模式更方便简单进行代码覆盖分析,无需提前进行字节码插桩,无需考虑classpath 的设置。
存在如下情况不适合on-the-fly,需要采用offline提前对字节码插桩:
(1)运行环境不支持java agent。
(2)部署环境不允许设置JVM参数。
(3)字节码需要被转换成其他的虚拟机如Android Dalvik VM。
(4)动态修改字节码过程中和其他agent冲突。
(5)无法自定义用户加载类。
2.JaCoCo执行最小的java版本
最小需要Java1.5
3.字节码处理方式
JaCoCo通过注入来修改和生成java字节码,使用的是ASM库。
4.java方法控制流分析
JaCoCo是如何在字节码注入的?
我们带着疑问来看下面的内容:
先举个实例,有个java方法:

编译后转换成字节码后,内容如下:

我们知道JaCoCo是字节码注入方式,它是通过一个Probe探针的方式来注入的,具体如下:
探针是字节指令集插入到java方法中,程序执行后可以被记录,它不会改变原有代码的行为。
我们看看探针前后插入比较:

颜色的部分就是探针注入的地方。
JaCoCo是根据控制流Type来采用不同的探针插入策略的。
一个用java字节码定义的java方法的控制流图可能有以下的type,每一个type连接一个源指令与目标指令,type不同探针的注入策略也会不同,如下是type定义:

探针不改变该方法的行为,但记录他们已被执行的事实,从理论上讲,可以在控制流图的每一个边插入一个探针,作为探针实现本身需要多个字节码指令,这将增加几倍的类文件的大小和执行速度。
事实上,只需要一个几个探头,根据每个方法的控制流的方法,下面说明了如何在不同的边缘类型的情况下添加额外的指令:


一个instrumented class可以用以下代码检索其探针数组实例:

JaCoCo是用一个布尔数组来实现探针,每个探针对应于该数组中的项。当以下四个字节码指令触发时探针进行输入设置为true:

JaCoCo对行探针是这样处理的,添加两行指令之间的一个额外的探针时,后续行至少包含一个方法调用。
以上是JaCoCo插桩原理,如果想深入了解,可以去看看它的源码实现。
1.3 JaCoCo使用方式
使用方式有很多,这里贴出了相应的参考链接,根据项目的不同可以灵活供有需要的读者去学习。
1.3.1 Apache Ant方式
参见 http://eclemma.org/jacoco/trunk/doc/ant.html
主要有以下几种,具体使用就不介绍了,应用宝是用的这种方式,后续有介绍。
Task coverage、Task agent、Task dump、Task merge、Task report、Task instrument
1.3.2 命令行方式
参见 http://www.eclemma.org/jacoco/trunk/doc/agent.html
使用方式说明:

主要放在JAVA_OPTS中,比如:

由AgentOptions的getVMArgument方法加载,各参数入AgentOptions的对应参数,为后续操作做为输入。

下面是官网的所有参数说明:

系统在jvm停止的时候会dump覆盖率信息。
关键的核心代码在这里,Agent.java在有一段代码

Runtime.getRuntime().addShutdownHook这个方法的意思就是在jvm中增加一个关闭的钩子,当jvm关闭的时候,会执行系统中已经设置的所有通过方法addShutdownHook添加的钩子,当系统执行完这些钩子后,jvm才会关闭。所以这些钩子可以在jvm关闭的时候进行内存清理、对象销毁等操作。
也就是在JVM关闭的时候调用agent.shutdown(),也就是写覆盖率数据。

1.3.3 Apache Maven方式
参见 http://www.eclemma.org/jacoco/trunk/doc/maven.html
这种方式适合Maven的项目。
下面简单说下调用方式原理:
就拿官方的Offline Example来说吧,其内容如下:

注意蓝色的部分,上面的配置主要做了以下几个事情:
(1)项目已jar包方式打包,引入junit和jacoco。
(2)Build时执行instrument、report、check。
(3)覆盖率生成到target/jacoco.exec
我们看看他是怎么触发调用的。
在jacoco源码中:jacoco-maven-plugin\target\classes\META-INF\maven\org.jacoco\jacoco-maven-plugin目录下有个plugin-help.xml文件,它里面标明了具体的调用方式。
截出instrument这段,关键地方就是下面蓝色部分。

官网上关于参数的说明:

给出一个整理后的表格:

再给一个jacoco的maven部分的代码目录:

到这里,大家应该清楚其调用的方式了吧。
1.3.4 Eclipse EclDmma Plugin方式
具体步骤如下:
(1)在Eclipse菜单中选择Help → Install New Software…
(2)在安装弹框中输入http://update.eclemma.org/,勾选出现的版本。

(3)核对版本,点击Next。
(4)根据向导完成安装。
(5)使用就不说了。
1.3.5 与Jekins集成
(1)先要在jenkins上安装JaCoCo的插件,安装完成之后在job的配置项中可以增加这个选项(如图1-2):

图1-2
(2)选择后出现(图1-3):

图1-3
第一个录入框是你的覆盖率文件(exec),第二个是class文件目录,第三个是源代码文件目录。
(3)配置好了之后进行构建,构建完成之后job首页就会出现覆盖率的趋势图(图1-4),鼠标点击趋势图可以看到覆盖率详情(图1-5) ,包括具体覆盖率数据和源码的覆盖率情况:

图1-4 趋势图

图1-5 覆盖率详情
未完待续:
JaCoCo原理篇就介绍到这里了,后续还有项目实践篇和踩坑篇,实践篇主要介绍下JaCoCo在实际业务中的使用情况,踩坑篇里面包含了几个当时遇到的比较棘手的问题的解决思路,有兴趣的童鞋请关注。
JAVA代码覆盖率工具JaCoCo-原理篇的更多相关文章
- java并发编程系列原理篇--JDK中的通信工具类Semaphore
前言 java多线程之间进行通信时,JDK主要提供了以下几种通信工具类.主要有Semaphore.CountDownLatch.CyclicBarrier.exchanger.Phaser这几个通讯类 ...
- 高效使用Java构建工具,Maven篇|云效工程师指北
大家好,我是胡晓宇,目前在云效主要负责Flow流水线编排.任务调度与执行引擎相关的工作. 作为一个有多年Java开发测试工具链开发经验的CRUD专家,使用过所有主流的Java构建工具,对于如何高效使用 ...
- 单元测试-代码覆盖率工具 -- JaCoCo
最近学习Mybatis的官方文档,看到了[项目文档]一节有很多内容没有见过,做个笔记,理解一下. 随着敏捷开发的流行,编写单元测试已经成为业界共识.但如何来衡量单元测试的质量呢?有些管理者片面追求单元 ...
- GoldenGate for Java Adapter介绍一(原理篇)
前言 Oracle Goldengate在很早前就推出了一个for java的版本,主要目的是方便把关系型数据实时写入到不支持的目标端,如JMS或Redis等key value数据库.在Hadoop刚 ...
- 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language- ...
- [转]深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)
以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-l ...
- 常用 Java Profiling 工具的分析与比较
转自:http://www.ibm.com/developerworks/cn/java/j-lo-profiling/index.html 在 Java 程序的开发过程中,不可避免地会遇到内存使用. ...
- 深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)
转载:http://zh.lucida.me/blog/java-8-lambdas-inside-out-library-features/ 关于 深入理解 Java 8 Lambda(语言篇——l ...
- Java开发工具IntelliJ IDEA单元测试和代码覆盖率图解
原文 http://www.cnblogs.com/xiongmaopanda/p/3314660.html Java开发工具IntelliJ IDEA使用教程:单元测试和代码覆盖率 本文将展示如何使 ...
随机推荐
- 1 创建一个存储过程,以及对存储过程的调用 MySQL
1 首先创建一张tb1表 sql语句如下 CREATE TABLE `tb1` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `age` int(11) DE ...
- Codeforces 570 - A/B/C/D/E - (Done)
链接:https://codeforces.com/contest/570 A - Elections - [水] AC代码: #include<bits/stdc++.h> using ...
- ZOJ 4060 - Flippy Sequence - [思维题][2018 ACM-ICPC Asia Qingdao Regional Problem C]
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4060 题意: 给出两个 $0,1$ 字符串 $S,T$,现在你有 ...
- js中触摸相关变量touches,targetTouches和changedTouches的区别
touches: 当前屏幕上所有触摸点的列表; targetTouches: 当前对象上所有触摸点的列表; changedTouches: 涉及当前事件的触摸点的列表 通过一个例子来区分一下触摸事件中 ...
- Vue中computed,methods 和watch
Vue中的计算属性和方法属性 1.计算属性 computed 模版中可以使用表达式 <div id="example"> {{ message.split('').re ...
- 前后端分离项目,标准json协议格式参考
正常返回 { "code": 0, "data": [{ "cTime": "2018-11-19 14:46:16" ...
- DIOCP3-粘包处理
DIOCP3-粘包处理 什么是粘包: 第一次发送 12345, 第二次发送abcde, 底层socket可能会一次性进行发送12345abcde,或者对方可能一次性进行了接收,那接收的时候,你可 ...
- 【托业】【跨栏】REVIEW2
supervise vt&vi 监督; 管理; 指导; storage capacity 存储空间,存储能力 be about to do sth =be going to do sth 将做 ...
- 消息摘要、哈希(hash)、加盐
hashlib 算法介绍: python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度 ...
- selenium启动Firefox失败
今天搭建java+selenium环境,搭建几次都失败,总结一下原因 1. selenium启动Firefox,不需要额外的driver 2. Friefox如果没有安装到默认路径C盘,代码中需要修改 ...