Search code examples
androidandroid-studiobuild.gradlejacocoandroid-jacoco

Jacoco: Report not generated for android project


I just integrated Jacoco code coverage for junit and UI test in my android studio project.

I added following steps:

In my app level build.gradle file:

apply plugin: 'jacoco'

and then added below code inside android { }

debug {
            testCoverageEnabled = true
            enableAndroidTestCoverage = true
            enableUnitTestCoverage = true
        }

and then added below code:

jacoco {
    toolVersion = "0.8.8"
}

tasks.withType(Test).configureEach {
    jacoco {
        excludes = [
                "**/R.class",
                "**/R\$*.class",
                "**/BuildConfig.*",
                "**/Manifest*.*",
                "**/*Test*.*"
        ]
    }
}


android {
    // Iterate over all application variants (e.g., debug, release)
    applicationVariants.configureEach { variant ->
        // Extract variant name and capitalize the first letter
        def variantName = variant.name.capitalize()

        // Define task names for unit tests and Android tests
        def unitTests = "test${variantName}UnitTest"
        def androidTests = "connected${variantName}AndroidTest"

        // Register a JacocoReport task for code coverage analysis
        tasks.register("Jacoco${variantName}CodeCoverage", JacocoReport) {
            // Depend on unit tests and Android tests tasks
            dependsOn(unitTests, androidTests)

            // Set task grouping and description
            group = "Reporting"
            description = "Execute UI and unit tests, generate and combine Jacoco coverage report"

            // Configure reports to generate both XML and HTML formats
            reports {
                xml.required = true
                xml.outputLocation = layout.buildDirectory.file("jacoco/xml/${variantName}Coverage.xml")

                html.required = true
                html.outputLocation = layout.buildDirectory.dir("jacoco/html/${variantName}Coverage.html")
            }

            // Set source directories to the main source directory
            sourceDirectories.setFrom(layout.projectDirectory.dir("src/main"))

            // Set class directories to compiled Java and Kotlin classes, excluding specified exclusions
            classDirectories.setFrom(files(
                    fileTree(dir: layout.buildDirectory.dir("intermediates/javac/")) {
                        exclude "**/R.class", "**/R\$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*Test*.*"
                    },
                    fileTree(dir: layout.buildDirectory.dir("tmp/kotlin-classes/")) {
                        exclude "**/R.class", "**/R\$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*Test*.*"
                    }
            ))

            // Collect execution data from .exec and .ec files generated during test execution
            executionData.setFrom(files(
                    fileTree(dir: layout.buildDirectory) { include "**/*.exec", "**/*.ec" }
            ))
        }
    }
}

But still code coverage report not generated in my android studio.


Solution

    1. Adding JaCoCo Plugin

      JaCoCo is enabled by adding the following to build.gradle:

      apply plugin: 'jacoco'

    2. Configuring JaCoCo:

      JaCoCo is configured to include/exclude specific files in build.gradle:

    > tasks.register('jacocoDebugReport', JacocoReport) {
    >     dependsOn 'connectedDebugAndroidTest'  // Ensure tests run before generating the report
    >     reports {
    >         xml.required.set(true)
    >         html.required.set(true)
    >     }
    > 
    >     def fileFilter = [
    >             '**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*',
    >             '**/*Test*.*', 'android/**/*.*' // Exclude this specific test class
    >     ]
    > 
    >     def debugTree = fileTree(dir: "${buildDir}/intermediates/javac/Debug", excludes:
    > fileFilter)
    >     def kotlinDebugTree = fileTree(dir: "${buildDir}/tmp/kotlin-classes/Debug", excludes:
    > fileFilter)
    > 
    >     sourceDirectories.setFrom(files("${project.projectDir}/src/main/java"))
    >     classDirectories.setFrom(files([debugTree, kotlinDebugTree]))
    >     executionData.setFrom(fileTree(dir: "${buildDir}/outputs/code_coverage/DebugAndroidTest/connected/",
    > includes: ["**/*.ec"])) }
    
    1. Enabling Code Coverage in android {} Block Inside android {} and debug {}, enable test coverage:
    testCoverageEnabled = true
    enableAndroidTestCoverage = true
    enableUnitTestCoverage = true
    
    1. Sync Gradle and Run Tests:

    After configuring JaCoCo, sync Gradle and execute test cases.

    1. Running Tests and Generating Reports:

    For a Single Class Test in CommunitySetupTestInCompose

     > ./gradlew clean  
    ./gradlew connectedDebugAndroidTest
        > -Pandroid.testInstrumentationRunnerArguments.class=com.android.test.TestInComposeClass
        > ./gradlew jacocoDebugReport
        > -Pandroid.testInstrumentationRunnerArguments.class=com.android.test.TestInComposeClass
    

    For All Test Cases

    > > ./gradlew clean ./gradlew connectedDebugAndroidTest ./gradlew
    >     > jacocoDebugReport
    
    1. Locating the JaCoCo Report:

    Once executed, the JaCoCo coverage report will be available in the following folder:

    ${buildDir}/reports/jacoco/jacocoDebugReport/html/index.html Open index.html in a browser to view the coverage details.

    Note: mustRunAfter 'connectedDebugAndroidTest' This is used for generate report even if the test case failed.