android系统代码覆盖率,android 代码覆盖率

背景

项目使用的是small插件。一个app分为main和多个插件,为了统计插件的代码覆盖率。

1 修改插件

修改插件build.gradle

buildTypes {

release {

...

}

debug{

minifyEnabled false

testCoverageEnabled = true //打开debug版本的代码覆盖率开关

proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘

}

}

因为工程原因插件生成的classes文件在下次生成的时候会变动。因此要讲classes文件拷贝到其他位置暂存。

tasks.whenTaskAdded { task ->

if (task.name == ‘assembleRelease‘ || task.name == ‘assembleDebug‘) {

task.doLast {

println"copy classes to jacoco"def applicationId=android.defaultConfig.applicationId

def artifactName= applicationId.substring(applicationId.lastIndexOf(".") + 1, applicationId.length())

project.copy {

from"build/intermediates/classes/debug"into"${rootDir}/../jacoco/${artifactName}/classes/debug"}

}

}

}

2 修改main

main作为插件的容器,我们的测试代码也在这里。所有的测试用例继承于BaseTest.

给BaseTest的finishZ增加覆盖率保存功能。

@Overrideprotected voidfinished(Description description) {super.finished(description);

.....

generateEcFile(true);

}/*** 生成ec文件

*

*@paramisNew 是否重新创建ec文件*/

public static void generateEcFile(booleanisNew) {

SimpleDateFormat df= new SimpleDateFormat("yyyyMMdd_HHmmss");final String DEFAULT_COVERAGE_FILE_PATH = "/sdcard/coverage/" + String.format("coverage_%s.ec", df.format(newDate()));

LogUtils.i("生成覆盖率文件: " +DEFAULT_COVERAGE_FILE_PATH);

OutputStream out= null;

File mCoverageFilePath= newFile(DEFAULT_COVERAGE_FILE_PATH);try{if (isNew &&mCoverageFilePath.exists()) {

LogUtils.i("JacocoUtils_generateEcFile: 清除旧的ec文件");

mCoverageFilePath.delete();

}if (!mCoverageFilePath.exists()) {

File d= new File("/sdcard/coverage/");

d.mkdirs();

mCoverageFilePath.createNewFile();

}

out= new FileOutputStream(mCoverageFilePath.getPath(), true);

Object agent= Class.forName("org.jacoco.agent.rt.RT")

.getMethod("getAgent")

.invoke(null);

out.write((byte[]) agent.getClass().getMethod("getExecutionData", boolean.class)

.invoke(agent,false));

}catch(Exception e) {

LogUtils.i("generateEcFile: " +e.getMessage());

}finally{if (out == null)return;try{

out.close();

}catch(IOException e) {

e.printStackTrace();

}

}

}

编译main,生成测试apk和debug版本的apk.

3.测试

使用测试系统进行测试

4.收集所有测试被测收集的测试数据。

importsubprocessimportos,sys

o= subprocess.check_output([‘adb‘,‘devices‘])

ls= o.split(‘\n‘)for line inls:if line.endswith(‘device‘):

id_= line.split(‘\t‘)[0]

os.makedirs(‘./report/‘+id_)

c1= [‘adb‘,‘-s‘,id_,‘pull‘,‘/sdcard/coverage‘,‘./report/‘+id_]print ‘ ‘.join( c1 )

o1=subprocess.check_output(c1)print o1

5.建立新的gradle工程,生成报告。

新建文件夹jacocReport。

进入文件夹运行gradle init。

修改build.gradle

apply plugin: ‘jacoco‘buildscript {

repositories {

mavenLocal()

mavenCenter()

maven { url‘plugins‘}

}

dependencies {

classpath‘net.researchgate:gradle-release:2.4.1‘classpath‘com.android.tools.build:gradle:2.2.3‘}

}

allprojects {

repositories {

mavenLocal()

mavenCenter()

flatDir {

dirs‘libs‘}

}

}//首先先删除旧的merge结果文件

task removeOldMergeEc(type: Delete) {

delete"${rootDir}/../jacoco/coverageMerged/mergedcoverage.ec"}

task mergeReport(type:JacocoMerge,dependsOn:removeOldMergeEc){

group= "Reporting"description= "merge jacoco report."destinationFile= file("${rootDir}/../jacoco/coverageMerged/mergedcoverage.ec")//这里的ec_dir是存储ec文件的文件夹

FileTree tree = fileTree("$projectDir/../jacoco/report") {

include‘**/*.ec‘}

def cnt=0tree.each{

cnt++}

println"ec file conut:"+cnt//tree.each{f->println f}

executionData = tree //executionData(files)

}

["plugin1",‘plugin2‘].each { it1->task"Report$it1"(type: JacocoReport,dependsOn: [mergeReport]) {it ->println"I‘m task $it"group= "Reporting"description= "Generate Jacoco coverage reports after running tests."def pluginName1= "$it1"println pluginName1

reports {

xml.enabled= truehtml.enabled= true}

classDirectories=fileTree(

dir:"${rootDir}/../jacoco/${pluginName1}/classes/debug",

excludes: [‘**/R*.class‘,‘**/*$InjectAdapter.class‘,‘**/*$ModuleAdapter.class‘,‘**/*$ViewInjector*.class‘])

def coverageSourceDirs=[//不需要代码路径

]

sourceDirectories=files(coverageSourceDirs)

File f= new File("${rootDir}/../jacoco/coverageMerged/mergedcoverage.ec")

println""+f.exists()

println"" + f.length()+ " bytes"executionData= files("${rootDir}/../jacoco/coverageMerged/mergedcoverage.ec")

doFirst {//修改claess 文件

println "${rootDir}/../jacoco/${pluginName1}/classes/debug"

new File("${rootDir}/../jacoco/${pluginName1}/classes/debug").eachFileRecurse { file ->

if (file.name.contains(‘$$‘)) {

println"modify " +file.name

file.renameTo(file.path.replace(‘$$‘, ‘$‘))

}

}

}}

}

task allReport(dependsOn: [Reportplugin1,Reportplugin2]){

doLast{

println"done!"}

}

最后上目录

.

├── main#主apk代码的目录

├── jacoco #数据目录-存放ec文件,classes文件

├── jacocoReport #生成报告的工程目录 build.gradle在此

├── plugin1       #插件1

├── plugin2       #插件2

原文:http://www.cnblogs.com/guhan121/p/7763468.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值