Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradle task jacoco report generate empty html report file (No class files specified)

I would like to use Jacoco to generate a code coverage report on all my tests (androidTest + UnitTest).

So I implemented a step-by-step script (jacoco.gradle) to create a task that allowed me to generate a report that merged two code coverage reports.

My problem is that the html generated file is empty (in app\build\jacocoReport\index.html):

No class files specified. JaCoCo 0.8.3.201901230119

I execute 'testIntegrationDebugUnitTest' task :

  • androidTest code coverage report has been created on app/build/reports/coverage/integration/debug/index.html and it's ok.

  • A 'ec' file has been generated on app\build\outputs\code_coverage\integrationDebugAndroidTest\connected\Pixel_2_API_24(AVD) - 7.0-coverage.ec

  • A 'exec' file has been generated on app/build/jacoco/testIntegrationDebugUnitTest.exec

Do you have any idea where my problem comes from? Here is my code:

jacoco.gradle :

apply plugin: 'jacoco'

jacoco {
    toolVersion = "$jacocoVersion"
    reportsDir = file("$buildDir/jacocoReport")
}

project.afterEvaluate {

    android.applicationVariants.all { variant ->
        def variantName = variant.name
        def testTaskName = "test${variantName.capitalize()}UnitTest"
        def androidTestCoverageTaskName = "create${variantName.capitalize()}CoverageReport"

        tasks.create(name: "${testTaskName}Coverage", type: JacocoReport, dependsOn: ["$testTaskName", "$androidTestCoverageTaskName"]) {
            group = "Reporting"
            description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build."

            reports {
                xml.enabled = false
                html.enabled = true
                html.destination "$buildDir/jacocoReport"
            }

            def excludes = ['**/R*.class',
                            '**/*$InjectAdapter.class',
                            '**/*$ModuleAdapter.class',
                            '**/*$ViewInjector*.class'
            ]

            def debugTree = fileTree(dir: "$project.buildDir/intermediates/javac/debug", excludes: excludes)
            def mainSrc = "$project.projectDir/src/main/java"

            sourceDirectories = files([mainSrc])
            classDirectories = files([debugTree])
            executionData = fileTree(dir: project.buildDir, includes: [
                    "jacoco/${testTaskName}.exec", "outputs/code_coverage/${variantName}AndroidTest/connected/**/*.ec"
            ])
        }
    }
}

gradle project :

buildscript {
    ext.kotlin_version = '1.3.21'
    ext.jacocoVersion = '0.8.3'

    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'io.realm:realm-gradle-plugin:5.8.0'
        classpath 'com.google.gms:google-services:4.2.0'
        classpath 'io.fabric.tools:gradle:1.28.0'
        classpath "org.jacoco:org.jacoco.core:$jacocoVersion"
    }
}

task installGradle(type: Wrapper) {
    group = "*********"
    gradleVersion = '4.10.1'
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

app gradle :

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'realm-android'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'io.fabric'
apply from: '../scripts/jacoco.gradle'

android.applicationVariants.all { variant ->
    if (variant.name == 'demoDebug' || variant.name == 'evalDebug' || variant.name == 'stagingDebug') {
        project.tasks.getByName('process' + variant.name.capitalize() + 'GoogleServices').enabled = false
        project.tasks.getByName('fabricGenerateResources' + variant.name.capitalize()).enabled = false
    }
}

android {

    compileSdkVersion 28
    defaultConfig {
        applicationId "***********"
        minSdkVersion 23
        targetSdkVersion 28
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    buildTypes {
        debug {
            testCoverageEnabled true
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:support-v4:28.0.0'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    implementation 'com.android.support:design:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    implementation 'android.arch.lifecycle:extensions:1.1.1'
    implementation 'com.google.firebase:firebase-core:16.0.8'
    implementation 'com.crashlytics.sdk.android:crashlytics:2.9.9'

    testImplementation 'junit:junit:4.12'
    testImplementation 'org.mockito:mockito-core:2.25.1'
    testImplementation 'android.arch.core:core-testing:1.1.1'

    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    androidTestImplementation 'org.mockito:mockito-android:2.25.1'
    androidTestImplementation 'android.arch.core:core-testing:1.1.1'
}
like image 899
Dev Loots Avatar asked Apr 17 '19 09:04

Dev Loots


People also ask

What is the JaCoCo report aggregation plugin for Gradle?

The JaCoCo Report Aggregation plugin (plugin id: jacoco-report-aggregation) provides the ability to aggregate the results of multiple JaCoCo code coverage reports (potentially spanning multiple Gradle projects) into a single HTML report.

How do I generate a JaCoCo report?

By default, a HTML report is generated at $buildDir /reports/jacoco/test. While tests should be executed before generation of the report, the jacocoTestReport task does not depend on the test task.

What is the jacocoreport task used for?

The JacocoReport task can be used to generate code coverage reports in different formats. It implements the standard Gradle type Reporting and exposes a report container of type JacocoReportsContainer. Example 4. Configuring test task This feature requires the use of JaCoCo version 0.6.3 or higher.

Does jacocotestreport generate XML report?

We’ll occasionally send you account related emails. Already on GitHub? Sign in to your account Given a jacocoTestReport task, it does not generate xml report EVEN THOUGH it generates html reports correctly.


1 Answers

This is a common problem, you need to change the debugTree property to:

//java compiled classes
def javaTree = fileTree(dir: "$project.buildDir/intermediates/javac/debug/classes", excludes: fileFilter)
//kotlin compiled classes
def kotlinTree = fileTree(dir: "$project.buildDir/tmp/kotlin-classes/debug", excludes: fileFilter)
//...etc...
classDirectories.from = files([javaTree, kotlinTree])

debug can be any variant, you can use $variantName in place of it if you know what you are doing

like image 130
MatPag Avatar answered Oct 14 '22 21:10

MatPag