背景
项目使用的是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