本文主要是介绍基于gradle的jacoco offline模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
jacoco的官网:EclEmma - JaCoCo Java Code Coverage Library
gradle语法:任务依赖 - Gradle 用户指南官方文档中文版 - UDN开源文档
在使用jacoco的时候,有时候需要将当前待测试的java类,添加到@PrepareForTest() 中,这会导致生成的行覆盖html中,当前类的覆盖率是为0,网上说比较好的解决办法是,使用jacoco offline模式,但是网上给的参考大部分都是maven文件,或者给的gradle文件使用不了。
github上提供了两个比较好的示例:
示例一:GitHub - MohammadAlavi1986/gradle-jacoo-offline-instrumentation
该示例是基于java程序的gradle配置,不使用android程序
示例二:https://github.com/h8MyJob/PowerMockJacocoDemo
该示例比较老了,运行起来有很多问题。
下面是我运行成功的配置(摸索了好久。。。)
其中,gradle版本是:gradle-7.5-bin.zip
顶层的build.gradle文件:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {id 'com.android.application' version '7.4.1' apply falseid 'com.android.library' version '7.4.1' apply false
}
module的build.gradle文件:
//单元测试相关依赖testImplementation("org.powermock:powermock-module-junit4:2.0.7")testImplementation("org.powermock:powermock-module-junit4-rule:1.7.4")testImplementation("org.powermock:powermock-api-mockito2:2.0.7")testImplementation("org.powermock:powermock-core:2.0.7")testImplementation("org.mockito:mockito-core:3.11.2")testImplementation("junit:junit:4.13.2")testImplementation("android.arch.core:core-testing:1.1.1")testImplementation("org.mockito:mockito-inline:3.11.2")
最后 jacoco_offline.gradle 文件如下:
apply plugin: 'jacoco'configurations {jacocoAntjacocoRuntime
}// 设置 jacoco offline 模式的Report目录
def jacocoOfflineDir = layout.buildDirectory.dir('jacocoOfflineReport')jacoco {toolVersion = "0.8.11" // 升级最新的版本reportsDirectory = jacocoOfflineDir
}def offline_instrumented_outputDir = "$buildDir.path/intermediates/classes-instrumented/debugCoverage"tasks.withType(Test) {jacoco.includeNoLocationClasses = truejacoco.excludes = ['jdk.internal.*']
}// 设置原java文件的目录
def coverageSourceDirs = ['src/main/java'
]// 设置生成覆盖率报告时,需要排除的文件
def excludeFiles = ['**/R.class','**/R$*.class','**/Manifest*.*','**/*Test*.*','android/**/*.*','**/BuildConfig.*','**/**Bean.class','**/inputmethod/*','**/config/*.*','**/flex/*.*','**/AssetsUtils.class'
]// 设置生成覆盖率报告时,仅仅支持的文件
def includeFiles = ['**/BuildConfig.*','**/HCInfoUtil.*'
]def classFileDir = fileTree(dir: 'build/intermediates/javac/debug/classes',excludes: excludeFiles
// includes: includeFiles
)// (1)生成jacoco动态覆盖率报告(jacoco属于动态检查)
task jacocoTestReport(type: JacocoReport, dependsOn: "test") {group = "Reporting"description = "Generate Jacoco coverage reports"classDirectories.from = classFileDirgetSourceDirectories().setFrom(files(coverageSourceDirs))getExecutionData().setFrom(files('./build/jacoco/testDebugUnitTest.exec'))}jacocoTestReport {reports {xml.enabled falsehtml.enabled truehtml.destination file("build/test-results/jacocoHtml")}
}/*** jacoco offline instrumentation jacoco离线检查* 先生成原始的预检测的*.class,然后在此基础上生成.exec文件,而不是在运行中生成检测的class文件*/
task createOfflineTestCoverageReport(dependsOn: ['clean', 'instrument', 'testDebugUnitTest']) {group = "Reporting"doLast {ant.taskdef(name: 'report',classname: 'org.jacoco.ant.ReportTask',classpath: configurations.jacocoAnt.asPath)ant.report() {executiondata {ant.file(file: "$buildDir.path/jacoco/testDebugUnitTest.exec")}structure(name: 'Example') {classfiles {fileset(dir: "$project.buildDir/intermediates/javac/debug/classes")}sourcefiles {fileset(dir: 'src/main/java')}}// offline模式生成的报告路径,此报告不能排除文件,一般不用,而是在之后的task中生成 html 报告
// html(destdir: "$buildDir.path/reports/jacocoHtml")}}
}gradle.taskGraph.whenReady { graph ->if (graph.hasTask(instrument)) {tasks.withType(Test) {doFirst {systemProperty 'jacoco-agent.destfile', buildDir.path + '/jacoco/testDebugUnitTest.exec'classpath = files(offline_instrumented_outputDir) + classpath + configurations.jacocoRuntime}}}
}/** Instruments the classes per se*/
task instrument(dependsOn:'compileDebugUnitTestSources') {doLast {println 'Instrumenting classes'ant.taskdef(name: 'instrument',classname: 'org.jacoco.ant.InstrumentTask',classpath: configurations.jacocoAnt.asPath)ant.instrument(destdir: offline_instrumented_outputDir) {fileset(dir: "$buildDir.path/intermediates/javac/debug/classes")}}
}// 将 offline 模式生成的exec文件拷贝到另一个目录,与jacoco动态生成区分
task copyTask(dependsOn:['createOfflineTestCoverageReport']) {doLast{copy {from './build/jacoco/testDebugUnitTest.exec'into './build/jacoco/offline'}}
}// 删除 offline 生成的html报告,防止执行当前生成报告未更新
task deleteReportTask(type: Delete) {doLast {delete jacocoOfflineDir.get().toString()+'/jacocoTestReportOffline'}
}// 使用 offline 模式下的 exec 文件,生成html报告
task jacocoTestReportOffline(type: JacocoReport, dependsOn:['copyTask', 'deleteReportTask']) {group = "Reporting"description = "Generate Jacoco coverage reports"classDirectories.from = classFileDirgetSourceDirectories().setFrom(files(coverageSourceDirs))getExecutionData().setFrom(files('./build/jacoco/offline/testDebugUnitTest.exec'))
}// (2)生成 jacoco offline 模式的覆盖率报告
task GenerateJacocoOfflineCoverageReports(dependsOn:'jacocoTestReportOffline') {group = "Reporting"doLast {println '生成 jacoco offline 报告的路径:'println jacocoOfflineDir.get().toString() + '/jacocoTestReportOffline'}
}
这篇关于基于gradle的jacoco offline模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!