简单两步实现 Jacoco+Android 代码覆盖率的接入!(最新最全版)(一)

简介: 简单两步实现 Jacoco+Android 代码覆盖率的接入!(最新最全版)

前言


JaCoCo的概念我就不在这里复述了网上有很多资料介绍,这里主要提一下他的两种插桩模式:On-the-flyOffline


On-the-fly模式:

JVM中通过-javaagent参数指定特定的jar文件启动Instrumentation的代理程序,代理程序在通过Class Loader装载一个class前判断是否需要转换修改class文件,然后将统计代码插入class,测试覆盖率分析可以在JVM执行测试代码的过程中完成。


Offline模式:

在测试前先对文件进行插桩,然后生成插过桩的class或jar包,测试插过桩的class和jar包后,会生成动态覆盖信息到文件,最后统一对覆盖信息进行处理,并生成报告。


但在Android项目中只能使用JaCoCo的离线插桩模式,主要是因为Android系统破坏了JaCoCo的这种便利性,原因如下:


  1. Android虚拟机跟运行在服务器上的JVM不同,它所支持的字节码必须经过特殊的处理以支持Dalvik、ART等虚拟机,所以插桩必须在处理之前完成;
  2. Android虚拟机无法像服务器上的JVM那样可以通过参数的方式实现配置,所以应用启动的时候是没有机会直接配置dump输出方式获取覆盖率信息的;


背景


其实主要是基于两个痛点:


1、新功能测试和回归测试在手工测试的情况下,即便用例写的再怎么详细,也经常会有漏测的发生,这里一方面是因为现在大量互联网公司采用外包资源来做业务测试,而外包的工作质量无法有效评估,可能存在漏执行的情况,另外一方面是本身测试用例设计的不够完善导致没有覆盖到一些关键路径的代码分支,因此亟需一种可以度量手工测试完成后对代码覆盖情况的手段或者工具;


2、研发代码变更的影响范围难以精准评估,比如研发提交一个MR,这个MR到底影响了多少用例,在没有精准测试能力的情况下是很难给出的,而做精准测试,最重要的一环就是代码用例的关系库维护,如何生成代码跟用例的关系,就需要用到代码覆盖率的采集和分析能力了;


实战


其实基于jacoco来做Android端代码覆盖率的难点主要是各个项目的gradle插件依赖跟jacoco版本直接的兼容性问题,特别是在以及开发很多年的多模块项目下,这个问题尤为明显,另外网上虽然有很多相关的文章资料,但是要么是gradle插件依赖版本太低,要么就是jacoco版本、配置文件以及项目的开发环境没有说清楚或者写的有问题,导致最终很难按照说明完成接入。


因此我先说明一下我的依赖情况,我用的是4.0版本比较新,应该算是目前主流的项目开发环境了:



gradle插件版本:classpath 'com.android.tools.build:gradle:4.0.1'
gradle依赖版本:distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip

我这里直接以多模块项目为例,单模块项目修改jacoco.gradle配置文件中的源码路径和class文件路径即可。


第一步


在app模块下新建一个jacoco.gradle文件,具体代码如下所示:

apply plugin: 'jacoco'
android {
    buildTypes {
        debug {
            /**打开覆盖率统计开关**/
            testCoverageEnabled = true
        }
    }
}
//源代码路径,有多少个module,就在这里写多少个路径,如果你只有app一个module,那么就写一个就可以
def coverageSourceDirs = [
        '../app/src/main/java',
        '../common/src/main/java',
]
//class文件路径,如果你只有app一个module,那么就写一个就可以
def coverageClassDirs = [
        '/app/build/intermediates/javac/debug/classes',
        '/common/build/intermediates/javac/debug/classes',
]
//Jacoco 版本,建议用这个版本兼容性比较好
jacoco {
    toolVersion = "0.8.2"
}
//生成报告task
task jacocoTestReport(type: JacocoReport) {
    group = "JacocoReport"
    description = "Generate Jacoco coverage reports after running tests."
    reports {
        xml.enabled = true
        html.enabled = true
    }
    classDirectories.from = files(files(coverageClassDirs).files.collect {
        println("$rootDir" + it)
        fileTree(dir: "$rootDir" + it,
                // 过滤不需要统计的class文件
                excludes: ['**/R*.class',
                           '**/*$InjectAdapter.class',
                           '**/*$ModuleAdapter.class',
                           '**/*$ViewInjector*.class'
                ])
    })
    sourceDirectories.from = files(coverageSourceDirs)
    executionData.from = files("$buildDir/outputs/code-coverage/coverage.ec")
    doFirst {
        coverageClassDirs.each { path ->
            println("$rootDir" + path)
            new File("$rootDir" + path).eachFileRecurse { file ->
                if (file.name.contains('$$')) {
                    file.renameTo(file.path.replace('$$', '$'))
                }
            }
        }
    }
}
//初始化Jacoco Task
task jacocoInit() {
    group = "JacocoReport"
    doFirst {
        File file = new File("$buildDir/outputs/code-coverage/")
        if (!file.exists()) {
            file.mkdir();
        }
    }
}

其中class的文件路径,具体跟gradle的版本有关,需要查看你自己实际的路径,如下图:

image.png

然后在你的app模块下的build.gradle文件中依赖这个jacoco.gradle,如下所示:

apply from: 'jacoco.gradle'...do something
android {...}

我们再整理一个jacoco.gradle放在项目的根目录作为通用配置,内容如下:

apply plugin: 'jacoco'
android {
    buildTypes {
        debug {
            /**打开覆盖率统计开关**/
            testCoverageEnabled = true
        }
    }
}

image.png

如果需要统计子module中的代码覆盖率,那么需要在子module的build.gradle文件中添加如下依赖:

apply from: rootProject.file('jacoco.gradle')
相关文章
|
4月前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
Android远程连接和登录FTPS服务代码(commons.net库)
61 1
|
4月前
|
Android开发 Swift iOS开发
探索安卓与iOS开发的差异:从代码到用户体验
【10月更文挑战第5天】在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。它们在技术架构、开发环境及用户体验上有着根本的不同。本文通过比较这两种平台的开发过程,揭示背后的设计理念和技术选择如何影响最终产品。我们将深入探讨各自平台的代码示例,理解开发者面临的挑战,以及这些差异如何塑造用户的日常体验。
|
5月前
|
存储 Java Android开发
🔥Android开发大神揭秘:从菜鸟到高手,你的代码为何总是慢人一步?💻
在Android开发中,每位开发者都渴望应用响应迅速、体验流畅。然而,代码执行缓慢却是常见问题。本文将跟随一位大神的脚步,剖析三大典型案例:主线程阻塞导致卡顿、内存泄漏引发性能下降及不合理布局引起的渲染问题,并提供优化方案。通过学习这些技巧,你将能够显著提升应用性能,从新手蜕变为高手。
59 2
|
6月前
|
JSON JavaScript 前端开发
Android调用Vue中的JavaScript代码
Android调用Vue中的JavaScript代码
93 3
|
6月前
|
Java Android开发
Android项目架构设计问题之要提升代码的可读性和管理性如何解决
Android项目架构设计问题之要提升代码的可读性和管理性如何解决
53 0
|
6月前
|
安全 Java 网络安全
Android远程连接和登录FTPS服务代码(commons.net库)
很多文章都介绍了FTPClient如何连接ftp服务器,但却很少有人说如何连接一台开了SSL认证的ftp服务器,现在代码来了。
134 2
|
7月前
|
存储 Java Android开发
🔥Android开发大神揭秘:从菜鸟到高手,你的代码为何总是慢人一步?💻
【7月更文挑战第28天】在Android开发中,每位开发者都追求极致的用户体验。然而,“代码执行慢”的问题时常困扰着开发者。通过案例分析,我们可探索从新手到高手的成长路径。
53 3
|
7月前
|
API Android开发
Android 监听Notification 被清除实例代码
Android 监听Notification 被清除实例代码
|
7月前
|
Web App开发 JavaScript 前端开发
Android端使用WebView注入一段js代码实现js调用android
Android端使用WebView注入一段js代码实现js调用android
182 0
|
8月前
|
存储 算法 Java
Android 进阶——代码插桩必知必会&ASM7字节码操作
Android 进阶——代码插桩必知必会&ASM7字节码操作
399 0

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    Android历史版本与APK文件结构
  • 3
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 6
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 7
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 8
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 10
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 1
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    14
  • 2
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    28
  • 3
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    34
  • 4
    Android历史版本与APK文件结构
    121
  • 5
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    29
  • 6
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    23
  • 7
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    60
  • 8
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    37
  • 9
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    73
  • 10
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    121