0

I wanted:

  1. Code coverage to run reliably against the instrumented tests
  2. Tests to be isolated from each other

I'm new to Android development, but experienced with other development and tooling.

So I looked for the documented options and added the following to my build.gradle:

android {
    defaultConfig {testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        testInstrumentationRunnerArguments clearPackageData: 'true'
        testInstrumentationRunnerArguments useTestStorageService: 'true'
    }

    buildTypes {
        debug {
            testCoverageEnabled true
        }
    }

I also have a custom task to generate the report:

task coverageReport(type: JacocoReport) {
    sourceDirectories.setFrom(fileTree(
            dir: "$project.buildDir/src/main/java"
    ))
    classDirectories.setFrom(fileTree(
            dir: "$project.buildDir/build/intermediates/javac/debug",
    ))
    executionData fileTree(dir: project.buildDir, includes: [
            "outputs/code_coverage/debugAndroidTest/connected/*/*.ec"
    ])
}

Now what I see when running the tests and generating the report, is that about 10% of the time it hits what looks like a corrupted .ec file. (the rest of the time, the report is fine)

> ./gradlew coverageReport
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:coverageReport'.
> Unable to read execution data file app/build/outputs/code_coverage/debugAndroidTest/connected/Nexus_S_API_33(AVD) - 13/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec

Digging into the stack trace:

Caused by: : Unable to read execution data file app/build/outputs/code_coverage/debugAndroidTest/connected/Nexus_S_API_33(AVD) - 13/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
        at org.jacoco.ant.ReportTask.loadExecutionData(ReportTask.java:518)
...
Caused by: java.io.IOException: Unknown block type 3.
        at org.jacoco.core.data.ExecutionDataReader.readBlock(ExecutionDataReader.java:119)
        at org.jacoco.core.data.ExecutionDataReader.read(ExecutionDataReader.java:93)
        at org.jacoco.core.tools.ExecFileLoader.load(ExecFileLoader.java:60)
        at org.jacoco.ant.ReportTask.loadExecutionData(ReportTask.java:516)

I've seen several other numbers in other projects for the unknown block type, but so far only 3 for this minimal example project.

MD5 sums are the same for the .ec files on and off the device:

> adb shell md5sum /data/media/0/googletest/internal_use/data/data/com.example.coverage/coverage_data/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
89c6b7ac8ad27d4d2f19dce0ac47f028  /data/media/0/googletest/internal_use/data/data/com.example.coverage/coverage_data/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
> md5sum app/build/outputs/code_coverage/debugAndroidTest/connected/Nexus_S_API_33\(AVD\)\ -\ 13/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec 
89c6b7ac8ad27d4d2f19dce0ac47f028  app/build/outputs/code_coverage/debugAndroidTest/connected/Nexus_S_API_33(AVD) - 13/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec

Re-running the tests will generally clear the issue on this project. On a larger project, several tests fail like this on each run - different tests each time, though apparently some more than others. It doesn't appear to be linked to the running time of the test.

I tried different versions of:

  • Gradle (7.4, 7.5, 8.0-rc-1, 8.0-rc-2)
  • AGP (7.4, 8.1.0-alpha01)
  • Android Studio (Eel, Giraffe)
  • emulator SDK version (27, 31, 33) with the same failing on each.

Syncing with Gradle files and cleaning/rebuilding don't help, and I've seen this happen on the first run of a new project.

I can see that:

  • Gradle support for Android lags (the new JaCoCo aggregate report plugin is explicitly not supported on Android)
  • Gradle's had and fixed some similar issues with JaCoCo in recent releases (e.g. https://github.com/gradle/gradle/issues/20532)
  • a similar issue's been seen with JaCoCo in other contexts (e.g. JaCoco MVN unknown block type which suggests the JVM's being hard-killed between tests)

Turning off clearPackageData doesn't stop these failures.

I was expecting code coverage of instrumented tests to be a core tool in my development process. So far it looks like either this error is a "me" problem, or Android devs don't see much value in having this working reliably. Any insights into why it's not that valuable or can be easily replaced would be as welcome as a fix.

Creon
  • 1
  • 3
  • Not the first time this has been seen, but reports were ferreted away and not discoverable from Google+SO. Here are some other cases: https://issuetracker.google.com/issues/266538654 https://issuetracker.google.com/issues/203448784 https://github.com/android/testing-samples/pull/411 – Creon Jan 27 '23 at 12:24
  • Can't reproduce the issue on a physical device. It's about 5 times slower than the emulator, so I don't know if it's more likely to be timing or environment that makes the difference. Looks like this unblocks me, though I'd prefer to have the emulator working. – Creon Jan 27 '23 at 15:51
  • Same issue after upgrading from gradle plugin 8.0.1 to 8.1.0 after upgrading from Eel to Giraffe. I have been researching a lot since I run into issues with getting coverage with instrumentation and there are several year old bugs that Google is not interested in fixing. Like instrumentation with coverage and Hilt is impossible currently. I suppose removing the instrumentation and isolating tests and writing tear downs could work, but idk. – John Glen Jul 26 '23 at 15:07

0 Answers0