Open kevalpatel2106 opened 1 year ago
Unfortunately it looks like this repo is abandoned. I've spent the last few days bashing away at replacing this plugin for my own project and seem to have gotten my own script working. There are many, many similar examples online but most of them are out of date (Android Gradle Plugin/Gradle seem to break things every major release 🙄), so as of May 2023 the following works for my project.
Import the following into each of your module build.gradle
s by adding
apply from: "$rootProject.projectDir/jacoco.gradle"
I'm currently using Gradle 8.0 and Jacoco 0.8.8 (I have this defined in the root project's build.gradle
)
buildscript {
ext {
jacocoVersion = '0.8.8'
}
}
jacoco.gradle I only ever run this Gradle task on my project's internalDebug build. If you don't have build flavors or want to do something different, you may need to modify this slightly.
apply plugin: 'jacoco'
jacoco {
toolVersion = "$jacocoVersion"
}
// Force Jacoco Version
subprojects {
configurations.all {
resolutionStrategy {
eachDependency { details ->
if ('org.jacoco' == details.requested.group) {
details.useVersion "$jacocoVersion"
}
}
}
}
}
project.afterEvaluate { project ->
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
final flavor = "internal"
final buildType = "debug"
final variant = "$flavor${buildType.capitalize()}"
final taskName = "jacocoTest${variant.capitalize()}UnitTestReport"
task "$taskName"(type: JacocoReport, dependsOn: "test${variant.capitalize()}UnitTest") {
reports {
csv.required = false
xml.required = true
html.required = true
}
final fileFilter = [
// data binding
'**/databinding/*',
'android/databinding/**/*.class',
'**/android/databinding/*Binding.class',
'**/android/databinding/*',
'**/androidx/databinding/*',
'**/BR.*',
// android
'**/R.class',
'**/R$*.class',
'**/BuildConfig.*',
'**/Manifest*.*',
'**/*Test*.*',
'android/**/*.*',
// kotlin
'**/*MapperImpl*.*',
'**/*$ViewInjector*.*',
'**/*$ViewBinder*.*',
'**/BuildConfig.*',
'**/*Component*.*',
'**/*BR*.*',
'**/Manifest*.*',
'**/*$Lambda$*.*',
'**/*Companion*.*',
'**/*Module*.*',
'**/*Dagger*.*',
'**/*Hilt*.*',
'**/*MembersInjector*.*',
'**/*_MembersInjector.class',
'**/*_Factory*.*',
'**/*_Provide*Factory*.*',
'**/*Extensions*.*',
// sealed and data classes
'**/*$Result.*',
'**/*$Result$*.*',
// adapters generated by moshi
'**/*JsonAdapter.*',
// Hilt
'**/*Module.kt',
'**/di/**',
'dagger.hilt.internal/*',
'hilt_aggregated_deps/*',
'**/*$Result.*', /* filtering `sealed` and `data` classes */
'**/*$Result$*.*',/* filtering `sealed` and `data` classes */
'**/*Args*.*', /* filtering Navigation Component generated classes */
'**/*Directions*.*', /* filtering Navigation Component generated classes */
'**/*inlined*.class', /* filtering inlined classes */
'**/composables/**'
/* INSERT ANY OTHER JUNK YOU WANT FILTERED OUT HERE */
]
final androidKotlinTree = fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/${variant}", excludes: fileFilter)
final kotlinTree = fileTree(dir: "${project.buildDir}/classes/kotlin/main", excludes: fileFilter)
final javacTree = fileTree(dir: "${project.buildDir}/intermediates/javac/${variant}/classes", excludes: fileFilter)
final mainSrc = "${project.projectDir}/src/main/java"
final productFlavorSrc = "${project.projectDir}/src/${flavor}/java"
final buildTypeSrc = "${project.projectDir}/src/${buildType}/java"
sourceDirectories.setFrom files([mainSrc, productFlavorSrc, buildTypeSrc])
classDirectories.setFrom files([androidKotlinTree, kotlinTree, javacTree])
executionData.setFrom fileTree(dir: project.buildDir, includes: [
"jacoco/test${variant.capitalize()}UnitTest.exec",
"outputs/unit_test_code_coverage/${variant}UnitTest/test${variant.capitalize()}UnitTest.exec",
])
}
}
Note: that this script does NOT put the output files in the same directory that the plugin does. This is important if you're passing the coverage information off to something like Sonar.
If you're using Sonar, I'm setting the xmlReportPaths property to -
property 'sonar.coverage.jacoco.xmlReportPaths', "**/build/reports/jacoco/**/*.xml"
If set up correctly, running ./gradlew jacocoTestInternalDebugUnitTestReport
(or similar, depending on your build flavors) should generate the coverage information.
Note for the future - inevitably, Gradle/Android Gradle Plugin will probably break this again. Chances are, the sourceDirectories, classDirectories or executionData directories have changed. Note: I'm also not gathering coverage from integration tests, only unit tests, so if you need that, you'll probably need to add another path to the executionData array. At one point this directory was 'outputs/code-coverage/connected/*coverage.ec'
but I have no idea if it still is, as I don't need to gather it in my project so haven't looked into it.
Hope this helps someone.
I rewrote this plugin and removed all the usages of deprecated APIs (and also migrated to the new AGP variant API). It's working well with AGP 8.0.1 / Gradle 8.1.1 for me. I've published it to Maven Central so feel free to use it 😉 https://github.com/mxalbert1996/jacoco-android-gradle-plugin
When trying to build the project with gradle 8.0, and plugin version
0.1.5
, gradle throws following exception: