Running JaCoCo in Azure DevOps for Android : Could not find method jacocoTestReport()
Asked Answered
R

2

5

We have implemented Jacoco in our Android Kotlin project which we can call locally via ./gradlew clean build jacocoTestReport

However, when we deploy to VSTS/Azure DevOps it errors with:

2019-02-04T09:37:35.5760285Z BUILD SUCCESSFUL in 12s
2019-02-04T09:37:35.5760428Z 1 actionable task: 1 executed
2019-02-04T09:37:35.5801607Z SYSTEMVSSCONNECTION exists true
2019-02-04T09:37:35.5816653Z [command]C:\Windows\system32\cmd.exe /D /S /C "C:\vstsagent\A1\_work\2\s\ApolloClient\gradlew.bat clean build jacocoRootReport"
2019-02-04T09:37:36.7652264Z 
2019-02-04T09:37:36.7653533Z FAILURE: Build failed with an exception.
2019-02-04T09:37:36.7653767Z 
2019-02-04T09:37:36.7653947Z * Where:
2019-02-04T09:37:36.7654401Z Build file 'C:\vstsagent\A1\_work\2\s\ApolloClient\build.gradle' line: 44
2019-02-04T09:37:36.7654582Z 
2019-02-04T09:37:36.7654768Z * What went wrong:
2019-02-04T09:37:36.7654952Z A problem occurred evaluating root project 'ApolloClient'.
2019-02-04T09:37:36.7655191Z > Could not find method jacocoTestReport() for arguments [build_abtyecjstjhjqmdmcxnlw2kq0$_run_closure4$_closure8@50246031] on project ':app' of type org.gradle.api.Project.
2019-02-04T09:37:36.7655365Z 
2019-02-04T09:37:36.7655547Z * Try:
2019-02-04T09:37:36.7655747Z Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
2019-02-04T09:37:36.7655931Z 
2019-02-04T09:37:36.7656098Z * Get more help at https://help.gradle.org
2019-02-04T09:37:36.7656242Z 
2019-02-04T09:37:36.7656585Z BUILD FAILED in 1s
2019-02-04T09:37:37.1999815Z Error: C:\vstsagent\A1\_work\2\s\ApolloClient\gradlew.bat failed with return code: 1
2019-02-04T09:37:37.1999996Z     at ChildProcess.<anonymous> (C:\vstsagent\A1\_work\_tasks\Gradle_8d8eebd8-2b94-4c97-85af-839254cc6da4\2.143.2\node_modules\vsts-task-lib\toolrunner.js:639:25)
2019-02-04T09:37:37.2000102Z     at emitTwo (events.js:106:13)
2019-02-04T09:37:37.2000154Z     at ChildProcess.emit (events.js:191:7)
2019-02-04T09:37:37.2000226Z     at maybeClose (internal/child_process.js:886:16)
2019-02-04T09:37:37.2000286Z     at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)

What I don't understand is, is it looking for a task called jacocoRootReport or jacocoTestReport?

Rath answered 4/2, 2019 at 10:51 Comment(2)
I am having the same issue.Institutive
Me too. It's sad that a more than a year has passed and nobody has a fix for that.Disappear
R
2

I could not get the actual gradle process to create the reports so I found a work around

  • Set the gradle task to "build jacocoRootReport"
  • Use the "Publish Code Coverage Results" task (set up to use Jacoco)
Rath answered 5/3, 2019 at 7:31 Comment(0)
T
6

I also fell into this hole and Burf2000's answer got me some of the way out. Hopefully this will get other people the rest of the way. My project was plain Java as opposed to Kotlin like the original question but I think this will all be applicable.

Running Jacoco in Azure devops for android:

The Jacoco bit

This assumes you don't have a working Jacoco task to begin with. If you do, skip ahead to The Azure Devops bit.

  1. Add a Jacoco dependency in your top level build.gradle file:
 dependencies {
        ...
        classpath 'org.jacoco:org.jacoco.core:0.8.5'
    }
  1. Add a jacoco.gradle file to your application root. Mine looks like this:
apply plugin: 'jacoco'

jacoco {
    toolVersion = "0.8.5"
}

def buildTypes = android.buildTypes.collect { type -> type.name }

buildTypes.each {
    buildTypeName ->
        def sourceName, sourcePath
        sourceName = sourcePath = "${buildTypeName}"
        def testTaskName = "test${sourceName.capitalize()}UnitTest"

        task "${testTaskName}Coverage" (type:JacocoReport, dependsOn: "$testTaskName") {
            group = "Reporting"
            description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build."
            logger.info(description)
            classDirectories = fileTree(
                    dir: "${project.buildDir}/intermediates/javac/${sourcePath}/classes",
                    excludes: ['**/R.class', '**/R$*.class', '**/*$ViewInjector*.*', '**/BuildConfig.*', '**/Manifest*.*'] )
            def coverageSourceDirs = [
                    "src/main/java",
                    "src/$buildTypeName/java"
            ]
            additionalSourceDirs = files(coverageSourceDirs)
            sourceDirectories = files(coverageSourceDirs)
            executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec")
            reports {
                xml.enabled = true
                html.enabled = true
            }
        }
}

It's pretty heavily cribbed from this blogpost. They also do test runs for different product flavours, which I have stripped it out. Aside from that, the main difference between the above and the linked blog is the classDirectories filepath.

  1. Apply jacoco.gradle in your app build script apply from: '../jacoco.gradle'

  2. Add testCoverageEnabled true to all buildTypes that you want coverage metrics to run on.

If you run ./gradlew tasks you should now see that you have some code coverage tasks under the reports heading. Run them and make sure they work as you're expecting as the feedback loop gets a lot slower in the next bit.

The Azure Devops bit

Burf2000 doesn't say how he got the Could not find method jacocoTestReport() ... error but I got it by setting the codeCoverageToolOption: to "jaCoCo" in my gradle task in my azure-pipelines.yml. Don't do this, it's a trap. The github docs for the gradle task tell you that you shouldn't use it if your build already has code coverage enabled.

Instead, you want to configure your Azure Devops Gradle task to call one of the Jacoco tasks you created earlier and then point a PublishCodeCoverageResults task at the generated XML. The relevant parts of my azure-pipelines.yml file look like this:

  - task: Gradle@2
    inputs:
      workingDirectory: ""
      ...
      tasks: "assemble test testReleaseUnitTestCoverage"

  - task: PublishCodeCoverageResults@1
    inputs:
      codeCoverageTool: "JaCoCo"
      summaryFileLocation: $(System.DefaultWorkingDirectory)/app/build/**/testReleaseUnitTestCoverage.xml
      pathToSources: $(System.DefaultWorkingDirectory)/app/src/main/java
      failIfCoverageEmpty: true
Tseng answered 21/4, 2020 at 11:59 Comment(2)
hey thanks for being specific, the official docs are not that helpfulBrann
this answer is a bit outdated, check this one medium.com/wandera-engineering/…Brann
R
2

I could not get the actual gradle process to create the reports so I found a work around

  • Set the gradle task to "build jacocoRootReport"
  • Use the "Publish Code Coverage Results" task (set up to use Jacoco)
Rath answered 5/3, 2019 at 7:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.