JaCoCo: Offline Instrumentations for Android & Gradle

Сабж занял довольно много времени - поэтому решил поделиться.
Буду предельно краток - так как проблема довольно узко-специализирована, и если человек будет искать решение, то ему все должно быть понятно.

Motivation:

Есть набор юнит-тестов для Android App написанных с использованием PowerMock и очень хотелось получить Coverage Report, но - There is NO WAY TO USE PowerMock with JaCoCo On-the-fly instrumentation

Solution:

Apply JaCoCo plugin:

apply plugin: 'jacoco'

configurations {
    jacocoAnt
}

jacoco {
    toolVersion = '0.8.1'
}

dependencies {
    jacocoAnt 'org.jacoco:org.jacoco.ant:0.8.1:nodeps'
    ..............................
}

Add task to generate instrumented classes:

task instrumentClasses(dependsOn : 'compileServerDebugSources') {
    def outputDir = "$buildDir.path/intermediates/classes-instrumented/server/debug"
    doLast {
        println 'Instrumenting classes'
        ant.taskdef(name: 'instrument',
                classname: 'org.jacoco.ant.InstrumentTask',
                classpath: configurations.jacocoAnt.asPath)
        ant.instrument(destdir: outputDir) {
            fileset(dir: "$buildDir.path/intermediates/classes/server/debug")
        }
        /* Add the instrumented classes to the beginning of classpath */
        testServerDebugUnitTest.classpath = files(outputDir) + testServerDebugUnitTest.classpath
    }
}

Add task to generate coverage report:

task createUnitTestCoverageReport(dependsOn: ['instrumentClasses', 'testServerDebugUnitTest']) {
    doLast {
        ant.taskdef(name: 'report',
                classname: 'org.jacoco.ant.ReportTask',
                classpath: configurations.jacocoAnt.asPath)
        ant.report() {
            executiondata {
                ant.file(file: "$buildDir.path/jacoco/testServerDebugUnitTest.exec")
            }
            structure(name: 'Example') {
                classfiles {
                    fileset(dir: "$project.buildDir/intermediates/classes/server/debug")
                }
                sourcefiles {
                    fileset(dir: 'src/main/java')
                }
            }
            html(destdir: "$buildDir.path/reports/jacoco")
        }
    }
}

Create coverage report:

gradlew createUnitTestCoverageReport
2 лайка

Столкнулся с такой же проблемой, пытаясь подружить JaCoCo с AspectJ:

https://github.com/sskorol/test-data-supplier/blob/master/build.gradle#L109-L153

1 лайк

В pure java все вроде бы просто и примеры в сети есть. Проблемы именно с комбо android+powermock+плагин_jacoco. Вот это например у меня не взлетело:

PS: И все-равно осталась небольшая проблема - вылетает покрытые с Robolectric.