关于JAVA代码覆盖率工具JaCoCo,做者会经过三篇来介绍,分别为原理篇、实践篇和踩坑篇,先从原理篇开始介绍~html
1、覆盖率定义java
做为一个测试人员,保证产品的软件质量是其工做首要目标,为了这个目标,测试人员经常会经过不少手段或工具来加以保证,覆盖率就是其中一环比较重要的环节。数组
咱们一般会将测试覆盖率分为两个部分,即“需求覆盖率”和“代码覆盖率”。jvm
需求覆盖:指的是测试人员对需求的了解程度,根据需求的可测试性来拆分红各个子需求点,来编写相应的测试用例,最终创建一个需求和用例的映射关系,以用例的测试结果来验证需求的实现,能够理解为黑盒覆盖。maven
代码覆盖:为了更加全面的覆盖,咱们可能还须要理解被测程序的逻辑,须要考虑到每一个函数的输入与输出,逻辑分支代码的执行状况,这个时候咱们的测试执行状况就以代码覆盖率来衡量,能够理解为白盒覆盖。函数
以上二者彻底能够相辅相成,用代码覆盖结果反向的检查需求覆盖(用例)的测试是否充分完整。工具
若是作覆盖率测试?咱们能够借助一些网上流行的各类覆盖率工具,本章主要介绍JaCoCo这个工具。学习
2、JAVA覆盖率工具介绍测试
市场上java主要代码覆盖率工具:EMMA、JaCoCo。ui
总结一下我的对JaCoCo优点的理解:
(1) JaCoCo支持分支覆盖、引入了Agent模式。
(2) EMMA官网已经不维护了,JaCoCo是其团队开发的,能够理解为一个升级版。
(3) JaCoCo社区比较活跃,官网也在不断的维护更新。
咱们前期使用的EMMA,也作了全量、差别覆盖率,和精准耦合也结合在了一块儿,但后来考虑到JaCoCo的优点,也就所有切换了过来。
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 覆盖率报告结果部分截图
标示绿色的为行覆盖充分,标红色的为未覆盖的行,黄色菱形的为分支部分覆盖,绿色菱形为分支彻底覆盖。
经过这个报告的结果就能够知道代码真实的执行状况,便于咱们分析评估结果。
2.2 JaCoCo基本概念
行覆盖率:度量被测程序的每行代码是否被执行,判断标准行中是否至少有一个指令被执行。
类覆盖率:度量计算class类文件是否被执行。
分支覆盖率:度量if和switch语句的分支覆盖状况,计算一个方法里面的总分支数,肯定执行和不执行的 分支数量。
方法覆盖率:度量被测程序的方法执行状况,是否执行取决于方法中是否有至少一个指令被执行。
指令覆盖:计数单元是单个java二进制代码指令,指令覆盖率提供了代码是否被执行的信息,度量彻底 独立源码格式。
圈复杂度:在(线性)组合中,计算在一个方法里面全部可能路径的最小数目,缺失的复杂度一样表示测 试案例没有彻底覆盖到这个模块。
2.3 JaCoCo 原理
一、注入方式介绍
这个图包含了几种不一样的收集覆盖率信息的方法,每种方法的实现方法都不同,带颜色的部分是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) 没法自定义用户加载类。
二、JaCoCo执行最小的java版本
最小须要Java1.5
三、字节码处理方式
JaCoCo经过注入来修改和生成java字节码,使用的是ASM库。
四、java方法控制流分析
JaCoCo是如何在字节码注入的?
咱们带着疑问来看下面的内容:
先举个实例,有个java方法:
编译后转换成字节码后,内容以下:
咱们知道JaCoCo是字节码注入方式,它是经过一个Probe探针的方式来注入的,具体以下:
探针是字节指令集插入到java方法中,程序执行后能够被记录,它不会改变原有代码的行为。
咱们看看探针先后插入比较:
颜色的部分就是探针注入的地方。
JaCoCo是根据控制流Type来采用不一样的探针插入策略的。
一个用java字节码定义的java方法的控制流图可能有如下的type,每个type链接一个源指令与目标指令,type不一样探针的注入策略也会不一样,以下是type定义:
探针不改变该方法的行为,但记录他们已被执行的事实,从理论上讲,能够在控制流图的每个边插入一个探针,做为探针实现自己须要多个字节码指令,这将增长几倍的类文件的大小和执行速度。
事实上,只须要一个几个探头,根据每一个方法的控制流的方法,下面说明了如何在不一样的边缘类型的状况下添加额外的指令:
一个instrumented class能够用如下代码检索其探针数组实例:
JaCoCo是用一个布尔数组来实现探针,每一个探针对应于该数组中的项。当如下四个字节码指令触发时探针进行输入设置为true:
JaCoCo对行探针是这样处理的,添加两行指令之间的一个额外的探针时,后续行至少包含一个方法调用。
以上是JaCoCo插桩原理,若是想深刻了解,能够去看看它的源码实现。
3、JaCoCo使用方式
使用方式有不少,这里贴出了相应的参考连接,根据项目的不一样能够灵活供有须要的读者去学习。
3.1 Apache Ant方式
参见 http://eclemma.org/jacoco/trunk/doc/ant.html
主要有如下几种,具体使用就不介绍了,应用宝是用的这种方式,后续有介绍。
Task coverage、Task agent、Task dump、Task merge、Task report、Task instrument
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(),也就是写覆盖率数据。
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部分的代码目录:
到这里,你们应该清楚其调用的方式了吧。
3.4 Eclipse EclDmma Plugin方式
具体步骤以下:
(1) 在Eclipse菜单中选择Help → Install New Software...
(2) 在安装弹框中输入http://update.eclemma.org/,勾选出现的版本。
(3) 核对版本,点击Next。
(4) 根据向导完成安装。
(5) 使用就不说了。
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在实际业务中的使用状况,踩坑篇里面包含了几个当时遇到的比较棘手的问题的解决思路,有兴趣的童鞋请关注。