3

Need help on enforcing code coverage metrics. I have based my solution on this blog post. I have already referred following posts in an attempt to solve this problem.

(Really embarrassing - still it looks like I'm missing something :( )

I am able to get the code coverage but not able to enforce minimum threshold.

Here is how my Jacoco.gradle looks like -

apply plugin: 'jacoco'
jacoco {
    toolVersion = "0.8.2"
}
project.afterEvaluate {
    // 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") {

                reports {
                    xml.enabled = true
                    html.enabled = true
                }
                group = "Reporting"
                description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
                classDirectories = fileTree(
                        dir: "${project.buildDir}/intermediates/javac/${buildTypeName}",
                        excludes: [
                            '**/R.class',
                            '**/R$*.class',
                            '**/*$ViewInjector*.*',
                            '**/*$ViewBinder*.*',
                            '**/BuildConfig.*',
                            '**/Manifest*.*'

                        ]
                )
                def coverageSourceDirs = [
                        "src/main/java",
                        "src/$productFlavorName/java",
                        "src/$buildTypeName/java"
                ]
                additionalSourceDirs = files(coverageSourceDirs)
                sourceDirectories = files(coverageSourceDirs)
                executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")

            }
        }
    }
}

I have included the above script in app module's build.gradle.

apply plugin: 'com.android.application'
apply from: '../jacoco.gradle'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.jacocodemo"
        minSdkVersion 27
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        
        debug {
            testCoverageEnabled = true
        }
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

I have tried many different approaches so far. Looks like the Jacoco documentation is biased towards plain java projects as the code snippets almost always need changes when used in android, but even then no luck.

Here's my attempt to solve this - (just give the Jacoco.gradle here as the main code is in it)

    apply plugin: 'jacoco'
    jacoco {
        toolVersion = "0.8.2"
    }

// ****** THIS IS MY ATTEMPT AT IT [START] ******
    task jacocoTestCoverageVerification(type: JacocoCoverageVerification) {
        violationRules {
            rule {
                enabled = true
                limit {
                    minimum = 0.9
                }
            }
        }
    }
    check.dependsOn jacocoTestCoverageVerification

// ****** THIS IS MY ATTEMPT AT IT [END] ******

    project.afterEvaluate {
        // 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") {

                    reports {
                        xml.enabled = true
                        html.enabled = true
                    }
                    group = "Reporting"
                    description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
                    classDirectories = fileTree(
                            dir: "${project.buildDir}/intermediates/javac/${buildTypeName}",
                            excludes: [
                                '**/R.class',
                                '**/R$*.class',
                                '**/*$ViewInjector*.*',
                                '**/*$ViewBinder*.*',
                                '**/BuildConfig.*',
                                '**/Manifest*.*'

                            ]
                    )
                    def coverageSourceDirs = [
                            "src/main/java",
                            "src/$productFlavorName/java",
                            "src/$buildTypeName/java"
                    ]
                    additionalSourceDirs = files(coverageSourceDirs)
                    sourceDirectories = files(coverageSourceDirs)
                    executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")

                }
            }
        }
    }

and then I tried invoking it as follows: gradle clean build testDebugUnitTestCoverage jacocoTestCoverageVerification. Any help on this is much appreciated.

0 Answers0