vanniktech/gradle-android-junit-jacoco-plugin

Jacoco Coverage report generated via Android gradle is empty

adityaagrawal167 opened this issue · 7 comments

Dear Team,

I want to implement Jacoco in my Android Studio (gradle v 3.5). Done all the changes required in both gradles. The jacoco report is getting generated but no coverage is there. Tried almost all commands.
Also, I am trying to generate this for my Local Unit test cases (not android tests).

Here I am attaching my both gradle files.

Please assist me on this as I am stuck from last one month.

Regards,
Aditya A

App Gradle
apply plugin: 'com.android.application'
apply plugin : 'jacoco'

android {
compileSdkVersion 30
buildToolsVersion "30.0.1"
defaultConfig {
applicationId "com.example.myfrstapp"
minSdkVersion 15
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
testCoverageEnabled false
}
debug{
testCoverageEnabled true
}
}
testOptions {
unitTests.all {
jacoco {
includeNoLocationClasses = true
}
}
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.0.0'
testImplementation 'junit:junit:4.13'
testImplementation 'org.mockito:mockito-core:1.10.19'
testImplementation 'org.powermock:powermock-core:1.7.0RC2'
testImplementation 'org.powermock:powermock-module-junit4:1.7.0RC2'
testImplementation 'org.powermock:powermock-api-mockito2:1.7.0RC2'
//testImplemetation 'org.robolectric:robolectric:2.3'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

}
task jacocoTestReport(type: JacocoReport, dependsOn: 'testDebugUnitTest') {
group="Reporting"
description="Generate Jacoco coverage Report"
reports {
xml.enabled = true
html.enabled = true
}
////
def fileFilter = ['/R*.class',
'
/$InjectAdapter.class',
'**/
$ModuleAdapter.class',
'/$ViewInjector.class',
'androidTest/
/.']

def debugTree = fileTree(dir: "$project.buildDir/tmp/java-classes/debug", excludes: fileFilter)

def mainSrc = "${project.projectDir}/src/main/java"
sourceDirectories = files([mainSrc])
classDirectories = files([debugTree])
executionData = fileTree(dir: project.buildDir, includes: [
        "jacoco/testDebugUnitTest.exec"
])

}


Project Gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
mavenCentral()
// maven {
// url "https://maven.google.com/"
// }
maven {
url "https://plugins.gradle.org/m2/"
}
jcenter()
}

dependencies {
    apply plugin: 'java'
    apply plugin: 'jacoco'
    apply plugin: 'application'
    classpath 'com.android.tools.build:gradle:3.5.0'
    classpath 'org.jacoco:org.jacoco.core:0.8.6'
    //classpath 'net.saliman:gradle-cobertura-plugin:3.0.0'

}

allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter()

    }
}

}

jacoco {
applyTo run
}

task applicationCodeCoverageReport(type:JacocoReport) {
executionData run
sourceSets sourceSets.main
}
task codeCoverageReport(type: JacocoReport) {
executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec")

subprojects.each {
    sourceSets it.sourceSets.main
}

reports {
    xml.enabled true
    xml.destination file("${buildDir}/reports/jacoco/report.xml")
    html.enabled true
    csv.enabled true
}

}
task jacocoRootTestReport(type: JacocoReport) {

sourceSets sourceSets.main

def jacocoTestFiles = ["$buildDir/jacoco/testDebugUnitTest.exec"]
subprojects.each { p ->
    def coverageFileLocation = "$p.buildDir/jacoco/testDebugUnitTest.exec"
    if (new File(coverageFileLocation).exists()) {
        jacocoTestFiles << coverageFileLocation
    }
}

logger.info('Aggregating next JaCoCo Coverage Files: {}', jacocoTestFiles)
executionData files(jacocoTestFiles)

reports {
    xml.enabled false
    csv.enabled false
    html.enabled true
}

}

codeCoverageReport.dependsOn {
subprojects*.test
}

Hey Aditya,

I am also facing the same issue, if you got anything please let me know!

Anyone, please suggest some solutions to the above issues.

Thanks,
Ajay

Is this still an issue? I know that every now and then when there's a new version, build directories are moved and need to be updated here.

Yes it looks like, I have a similar issue since I upgraded to android studio 4.2 (gradle plugin 4.2.0 and gradle 6.7.1) apparently.
The reports are generated, but coverage is 0%.
Also I have a strange app/jacoco.exec generated each time.

mfd03 commented

After upgrading my plugin version to 0.8.7 I had the same problem and I found out that the flag testCoverageEnabled is working in the opposite way as it should, generating correct coverage values when is set to false, and 0% coverage when is set to true.

@mfd03 looks like you are right. I upgraded jacoco to 0.8.7 and set testCoverageEnbaled to false and it works again with gradle plugin 4.2.0

Hello all,
Actually I am not using testCoverageEnabled in my project. It's not required for our project. We are using ./gradlew jacocoTestReportDebug to generate the report.

Below are the steps I tired:
Step 1: Till now used Java8 , upgrade this to Java11.
Step 2: Because of above upgrade got this error (Caused by: java.lang.ClassNotFoundException: jdk.internal.reflect.GeneratedSerializationConstructorAccessor1
)
Step 3: So used this below code snippet:
tasks.withType(Test) {
includeNoLocationClasses = true
jacoco.excludes = ['jdk.internal.*']
}

After that I am getting coverage report is zero.

I am also having this issue
plugin = 0.16.0
jacoco = 0.8.7
java = 11
gradle = 7.1.2

setting testCoverageEnabled = false made test coverage show correctly, while setting it to true made test coverage always 0% 🤔