Search code examples
androidgradlecode-coveragejacoco

How to run Jacoco for Android using Gradle?


I am trying to run Jacoco with Gradle for a sample Android App. I know that both Android and Java plugin cannot be included, so I believe that pre-instrumentation should be done for android code, before running tests to generate jacoco.exec file. However, I am getting TargetInvocationException, caused by java.lang.StackOverflowError while running my gradle build file. The error is:

FATAL ERROR in native method: processing of -javaagent failed

Here is my build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.8.+'
    }
}
apply plugin: 'android'
apply plugin: 'jacoco'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.1"

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            res.srcDirs = ['res']
            java.srcDir file('src')
        }
    }
}

    sourceSets {
        unitTest {
            java.srcDir file('unitTest/src')
        }
    }

    configurations {
        unitTestCompile.extendsFrom runtime
        unitTestRuntime.extendsFrom unitTestCompile
        codeCoverage
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        unitTestCompile files("$project.buildDir/classes/release")
        unitTestCompile 'junit:junit:4.11'
        unitTestCompile 'org.robolectric:robolectric:2.2'
        unitTestCompile 'com.google.android:android:4.0.1.2'
        codeCoverage 'org.jacoco:org.jacoco.agent:0.6.5.201403032054:runtime@jar'
    }

    tasks.whenTaskAdded { task ->
        if(task.name == 'unitTest'){
            task.jvmArgs "-javaagent:${configurations.codeCoverage.asPath}=destfile=${project.buildDir.path}/coverage-results/jacoco.exec,sessionid=HSServ,append=false",
                    '-Djacoco=true',
                    '-Xms128m',
                    '-Xmx512m',
                    '-XX:MaxPermSize=128m'
        }

    }
    task unitTest(type:Test, dependsOn: assemble){
        description = "run unit tests"
        testClassesDir = project.sourceSets.unitTest.output.classesDir
        classpath = project.sourceSets.unitTest.runtimeClasspath

        afterTest { desc, result ->
            println "Executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
        }
    }

build.dependsOn unitTest

What's wrong here?


Solution

  • Try out the new gradle plugin 0.10 which supports tests with Jacoco.

    dependencies {
        classpath 'com.android.tools.build:gradle:0.10.+'
    }
    

    From the tools.android.com page:

    Test code coverage support with Jacoco. Enable in the tested Build Type with testCoverageEnabled = true. HTML and XML Report generated in build/reports/coverage. Configure version of Jacoco with:

    android {
      jacoco {
        version = '0.6.2.201302030002'
      }
    }
    

    Known issue: This is not compatible with using Dagger.