14

Today I updated gradle and kotlin dependencies in android studio.

The new versions are these:

kotlin_version = "1.5.10"
...
jacoco {
    toolVersion = "0.8.6"
}
...
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip

The test coverage report task fails with the following error:

2021-05-27T16:57:49.150+0200 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter] Executing actions for task ':consumerkit:testDebugUnitTestCoverage'.
2021-05-27T16:57:49.304+0200 [DEBUG] [org.codehaus.groovy.vmplugin.VMPluginFactory] Trying to create VM plugin `org.codehaus.groovy.vmplugin.v9.Java9` by checking `java.lang.Module`, but failed:
java.lang.ClassNotFoundException: java.lang.Module
        at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at org.codehaus.groovy.vmplugin.VMPluginFactory.lambda$createPlugin$0(VMPluginFactory.java:61)
        at java.security.AccessController.doPrivileged(Native Method)
Ultimo_m
  • 4,724
  • 4
  • 38
  • 60
  • Why do you think that this is related to JaCoCo? Stack trace seems to be about Groovy. Anyway for Kotlin 1.5 you should use JaCoCo 0.8.7 instead of 0.8.6 - see https://github.com/jacoco/jacoco/pull/1164 So could you please try it? – Godin May 27 '21 at 21:22
  • @Godin I included jacoco because the task fails when it should generate the reports. And yes with the new update it works fine (you can post it as an answer). Thanks – Ultimo_m May 27 '21 at 21:36

4 Answers4

16

For Kotlin 1.5 you should use JaCoCo 0.8.7 instead of 0.8.6 - see https://github.com/jacoco/jacoco/pull/1164 and the full changelog at https://www.jacoco.org/jacoco/trunk/doc/changes.html

Example snippet:

// build.gradle or build.gradle.kts
jacoco {
    toolVersion = "0.8.7"
}
acdcjunior
  • 132,397
  • 37
  • 331
  • 304
Godin
  • 9,801
  • 2
  • 39
  • 76
5

I already had the

jacoco {
    toolVersion = "0.8.7"
}

configured but it was not working anyway, what fixed the problem was to follow this comment here

  1. In your module build.gradle switch back to:
android {
    //....
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}

don't worry, it won't break anything if you were not using Java 11 language features yet, AGP 7 is still compatible with JDK 8 as target.

  1. Then you need to force AGP to use the 0.8.7 version and not the default 0.8.3 one. In your allprojects block in the root build.gradle file, add this:
allprojects {
  //... other things

  // workaround to fix an auto-import of a lower Jacoco version
  resolutionStrategy {
    eachDependency { details ->
      if ('org.jacoco' == details.requested.group) {
        details.useVersion "0.8.7"
      }
    }
  }
}

and now it should work using:

AGP 7.0.X
Kotlin 1.5.X
JDK 11 (embedded with AS)
MatPag
  • 41,742
  • 14
  • 105
  • 114
  • this answer helped me. So when I upgraded source and target version to 11 I get this error PBI: {"kind":"error","text":"com.android.tools.r8.internal.r8: Unsupported dynamic constant: $jacocoData : Ljava/lang/Object; com/rules/Range.$jacocoInit any idea. – Rameshbabu Nov 29 '21 at 11:28
3

Simply doing

jacoco {
    toolVersion = "0.8.7"
}

was not enough for me. I also had to override the version that Android was using so that the androidJacocoAnt dependency also uses 0.8.7. (./gradlew app:dependencies) Simply add this to your gradle too

android.jacoco.version = "0.8.7"
Barry Irvine
  • 13,858
  • 3
  • 25
  • 36
2

It's quite old thread, but these solutions did not solve my problems completely in Android project (actually written in Java - not in Kotlin), so I will add my solutions here. Maybe someone will find it helpful.

Except of updating jacoco toolVersion to 0.8.7, I also had to update execution data in my jacoco config as follows:

project.afterEvaluate {
  tasks.create(name: "${unitTestTask}Coverage", type: JacocoReport, 
  dependsOn: [
    "$unitTestTask",
    ":sdk:testDebugUnitTest",
    ":sdk:connectedCheck"
  ]) {

   /* all jacoco custom configuration goes here... */

    executionData(fileTree(dir: "$buildDir", includes: [
      "jacoco/testDebugUnitTest.exec",        
      "outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec",
      "outputs/code_coverage/debugAndroidTest/connected/*coverage.ec"
    ]))
  }
}

in this configuration I had to add the following line:

"outputs/unit_test_code_coverage/debugUnitTest/testDebugUnitTest.exec"

which wasn't there before because file with generated report used by sonar was generated in the new location. Report is generated with gradle task testDebugUnitTestCoverage. After all of that, I'm able to generate test coverage report including connected/instrumentation Android tests and regular unit tests in java via sonar.

Piotr Wittchen
  • 3,853
  • 4
  • 26
  • 39
  • 1
    This really helped me, thanks Piotr. I was missing that the folder has now moved to`unit_test_code_coverage` – dev2505 Nov 07 '22 at 17:28