'File filter in Jacoco android test coverage report not working as expected
I am trying to add Jacoco to my project for test coverage reporting.
Referred the following blogs for that,
- https://medium.com/nerd-for-tech/setup-jacoco-code-coverage-with-your-multimodule-android-app-kotlin-a0f82573a1
- https://azizbekian.medium.com/setup-jacoco-sonarqube-in-multimodule-multiflavor-kotlin-android-project-d8e7b27aed36
- https://medium.com/jamf-engineering/android-kotlin-code-coverage-with-jacoco-sonar-and-gradle-plugin-6-x-3933ed503a6e
Most of them have the same code for file filtering, but it is not working for me.
jacoco.gradle
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.7"
}
project.afterEvaluate { project ->
setupAndroidReporting()
}
def setupAndroidReporting() {
tasks.withType(Test) {
// Whether or not classes without source location should be instrumented
jacoco.includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}
// Grab all build types and product flavors
def buildTypes = android.buildTypes.collect { type ->
type.name
}
def productFlavors = android.productFlavors.collect { flavor ->
flavor.name
}
// When no product flavors defined, use empty
if (!productFlavors) {
productFlavors.add('')
}
productFlavors.each { productFlavorName ->
buildTypes.each { buildTypeName ->
def sourceName, sourcePath
if (!productFlavorName) {
sourceName = sourcePath = "${buildTypeName}"
} else {
sourceName = "${productFlavorName}${buildTypeName.capitalize()}"
sourcePath = "${productFlavorName}/${buildTypeName}"
}
def testTaskName = "test${sourceName.capitalize()}UnitTest"
// Create coverage task of form 'testFlavorTypeCoverage' depending on 'testFlavorTypeUnitTest'
task "${testTaskName}Coverage"(type: JacocoReport, dependsOn: "$testTaskName") {
group = "Reporting"
description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
def fileFilter = [
// data binding
'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/*',
]
def javaTree = fileTree(dir: "${project.buildDir}/intermediates/javac/$sourceName/classes", exclude: fileFilter)
def kotlinTree = fileTree(dir: "${project.buildDir}/tmp/kotlin-classes/$sourceName", exclude: fileFilter)
classDirectories.from = files([javaTree], [kotlinTree])
executionData.from = files("${project.buildDir}/jacoco/${testTaskName}.exec")
def coverageSourceDirs = [
"src/main/java",
"src/$productFlavorName/java",
"src/$buildTypeName/java",
]
sourceDirectories.setFrom(files(coverageSourceDirs))
additionalSourceDirs.setFrom(files(coverageSourceDirs))
reports {
csv.enabled false // change if needed
xml.enabled false // change if needed
html {
enabled true
destination file("${buildDir}/coverage-report")
}
}
}
}
}
System.out.println("Test coverage report: ${buildDir}/reports/coverage/androidTest/debug/index.html")
}
// Jacoco
configurations.all {
resolutionStrategy {
eachDependency { details ->
if ('org.jacoco' == details.requested.group) {
details.useVersion "0.8.7"
}
}
}
}
The generated report still includes files from these hilt directories.
Note:
Also noticed it is not running/reporting any tests as the coverage is shown as 0%.
P.S: Please add a comment if any required info is missing in the question.
Solution 1:[1]
Please check additionalClassDirs
content. If it is not empty, try clearing it with classDirectories.setFrom(files())
. This should do the trick.
The coverage task does not have dependencies on test
or connectedTest
, so you have to run the tests manually before starting this task.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Yuriy Kulikov |