测试覆盖率是对测试实现水平的度量。它通常根据某种笼罩准则来对测试用例执行状况进行掂量,以判断测试执行得是否充沛
。
——出自《
计算机科学技术名词》第三版
明天文章中咱们给大家介绍覆盖率统计及覆盖率剖析。在 10 月 13 日 20:00,资深测试开发架构师思寒将光顾直播间手把手教大家如何搞定精准化测试!
舒适提醒:你认为代码覆盖率与精准化测试常识与黑盒测试无缘?不,你只是没遇到思寒讲的这节课。
常见覆盖率统计工具
- emma
- cobertura
- jacoco
emma 与 cobertura 是为单元测试而设计的覆盖率统计,jacoco 与 emma 同属于一家公司,然而是为了更宽泛的覆盖率统计而设计的工具。
Jacoco
jacoco 的文档中有个 mission 章节,外面对 jacoco 的定位形容的很好。原文的粗心是说其余的工具没有失去踊跃无效的保护,而且其余的工具都是为了繁多工作而设计,他们不是为了“集成”而生。从这一点上咱们就能够看出 jacoco 的设计理念。
得益于 jacoco 的设计理念,以及良好的 api 设计,它能够轻松的与已有的工具集成,甚至进行平台化。它也能够同时用于单元测试与集成测试,所以是一款十分优良的覆盖率统计工具,很多公司的精准化测试,就是重度依赖了 jacoco。
覆盖率剖析原理
要理解代码覆盖率的统计原理,咱们就须要去深刻理解 jvm 的机制。这方面的常识是 java 畛域的高端进阶常识,限于篇幅,咱们只解说下大略的原理,残缺内容请参考 VM 虚拟机系列的书籍,以及 newrelic 早年公布的若干代码插桩的材料。
简略说下原理,java 源代码会被 javac 编译为 class 文件,class 文件保留了 class 的根本信息与 jvm 的指令集。java 的底层 runtime,也就是 jvm 在解析 class 的时候,会把文件格式的 class 读取到内存并运行。android 也是借鉴了这一整套的设计理念,android 上的 runtime 其实是 dalvik 与 art。
当咱们要统计代码覆盖率的时候,就须要在代码的执行门路上退出探针剖析。通常是在读取类的时候,在要害的指令块的进口与入口减少标记。当指令块被执行后,就会命中探针并实现记录。
要批改最底层的 jvm 字节码往往是比拟麻烦的,须要精通 jvm 的各种指令以及 java class 构造。这方面的解决目前已有有十分成熟的开源我的项目能够做大了,如下就是一些出名的字节码批改工具。
- ASM
- JavaAssist
-
ByteBuddy、BTrace、JVM-Sandbox
其中 ASM 是所有字节码操作的底层根底,是最底层的字节码批改工具。其余工具是它之上的一些高级封装。借助于这些工具与 JVM 本身的一些调试个性,咱们就能够对 jvm 代码或者过程进行便捷的操纵了。插桩形式
插桩形式有很多种,常见的形式如下
- 源代码插桩:offline 插桩,反对 android
- 字节码插桩:offline 插桩,反对 android
-
javaagent 模式:脱离代码在运行时插桩,on the fly 模式
jacoco 反对字节码插桩与 javaagent 这两种插桩形式。也就是就算没有源代码也能够统计到覆盖率数据,然而最初剖析的时候,还是要联合源代码能力取得更多的覆盖率细节数据。毕竟覆盖率的统计,并不是只是简略的覆盖率数据自身的指标高下。jacoco 的工作形式
jacoco 反对四种工作模式
- file:过程完结的时候在本地生成文件
- tcpserver:开启端口期待客户端获取覆盖率
- tcpclient:被动把覆盖率数据发送进来
- none:不生成覆盖率
很多人都会应用 file 模式,然而 tcp server 模式才是最易用的。因为不须要申请服务器的文件拜访权限就可管制覆盖率数据。你能够依据本人公司的部署状况抉择适合的工作模式。
on the fly 插桩模式是应用最多的。首先须要在你的被测 java 程序启动的时候,退出 jvm 的一些 javaagent 参数。
-javaagent:[yourpath/]jacocoagent.jar=[option1]=[value1],[option2]=[value2]
destfile
output:file、tcpserver、tcpclient、none
address
port
你能够本人设置适宜的工作模式。
离线插桩模式,适宜 android 的覆盖率统计,须要借助于 maven、gradle 等构建工具的 instrument 指令。
jacoco-cli 是 jacoco 的一个组件,能够在不依赖 maven、gradle 构建工具的状况下实现对代码的剖析。次要用于 tcpserver 工作模式下。
用法如下
java -jar jacococli.jar dump [--address <address>] --destfile <path> [--help] \
[--port <port>] [--quiet] [--reset] [--retry <count>]
这是学院里的一个入手演练的小场景,统计 jmeter 工具的启动覆盖率
project_root=/Users/seveniruby/temp/java_2/jacoco/apache-jmeter-5.2.1
jacoco_cli_jar=org.jacoco.cli-0.8.6-20200329.124045-45-nodeps.jar
java -javaagent:org.jacoco.agent-0.8.6-20200329.124039-45-runtime.jar \
-jar $project_root/bin/ApacheJMeter.jar
#退出 jmeter
#生成覆盖率报告
java -jar $jacoco_cli_jar report jacoco.exec \
--classfiles "$project_root/bin/ApacheJMeter.jar" \
--classfiles $project_root/lib/ext/ApacheJMeter_http.jar \
--html jmeter_coverage/
#生成带有源代码的覆盖率报告
java -jar $jacoco_cli_jar report jacoco.exec \
--classfiles "$project_root/bin/ApacheJMeter.jar" \
--classfiles $project_root/lib/ext/ApacheJMeter_http.jar \
--html jmeter_coverage/ --sourcefiles ~/projects/jmeter/src/
#生成 xml 报告
java -jar $jacoco_cli_jar report jacoco_tcpserver2.exec \
--classfiles "$project_root/bin/ApacheJMeter.jar" \
--classfiles $project_root/lib/ext/ApacheJMeter_http.jar \
--xml jmeter_coverage_tcpserver2/jacoco.xml
残缺代码请参考学员论坛中的课程帖中的源代码。
sonarqube 能够剖析 jacoco 的 exec 文件与 xml 文件,并主动导入覆盖率。exec 文件的剖析后续会放弃反对,主反对 xml 文件的剖析。
sonar-scanner \
-Dsonar.host.url=http://sonarqube.testing-studio.com:9000 \
-Dsonar.login=$SONARQUBE_TOKEN \
-Dsonar.projectKey=jmeter \
-Dsonar.projectVersion=1.0 \
-Dsonar.coverage.jacoco.xmlReportPaths=$PWD/jmeter_coverage_tcpserver2/jacoco.xml \
-Dsonar.projectBaseDir=/Users/seveniruby/projects/jmeter/ \
-Dsonar.java.binaries=/Users/seveniruby/projects/jmeter/
导入覆盖率
能够通过如下参数限定要剖析代码的范畴,通常是指明要笼罩的 package 范畴
- sonar.sources
- sonar.inclusions
导入覆盖率
sonarqube 能够智能剖析新老版本之间的新增代码的覆盖率,这点十分不错,以前一些剖析代码 diff 的工作就节俭了。他的代码剖析也比拟智能,简略的换行并不会烦扰代码 diff 的剖析范畴。
通过覆盖率数据
sonarqube 反对两种通用的测试数据导入
- 通用覆盖率数据:sonar.coverageReportPaths
- 通用测试执行数据:sonar.testExecutionReportPaths
这样不便与各种框架进行集成,也不便测试工程师二次定制。
通用测试数据模板。
通用覆盖率数据模板
在 sonarqube 的 scanner 剖析中,退出对应的配置参数即可导入通用测试数据。
通用测试数据导入的常见用处
- 将各种测试工具的测试报告转换为 sonarqube 反对的格局从而导入平台
- 将各种覆盖率工具的覆盖率报告转换为规范格局导入平台
- 依据需要对差别 diff 覆盖率进行定制,比方除了对新增代码做笼罩,还要对应用了新增代码的依赖代码也做剖析
代码的 diff 剖析是一个比拟大的话题,diff 只是对代码的最简略的一个剖析策略,要想深刻的了解代码,咱们还须要更进一步的剖析代码的调用链。咱们先看最简略的代码 diff 剖析工具。
代码 diff 剖析工具
- JGit:git 剖析工具
- JavaParser:语法分析
- ASM:读取字节码
- javap:jdk 自带字节码剖析工具