Kotlin JaCoCo, no coverage -> IllegalClassFormatException … Please supply original non-instrumented classes

假如想象 提交于 2021-02-07 12:19:05

问题


kotlin verion: 1.3.61

Android Gradle Plugin: 3.5.3

JaCoCo Version: 0.8.4.201905082037 (default android gradle version)

project: https://github.com/goldy1992/Mp3Player/tree/feature/issue-112/migrate-to-kotlin

I have a multi module gradle project with: 2 flavours: full, automation 2 build types: release, debug

I'm in the process of migrating everything to kotlin.

Module structure

  • commons [android library] (works as expected with test coverage)
  • client-test-support (used for test implementations of activities)
  • client [android library] (no coverage) -> depends on commons, client-test-support
  • service-test-support (used for test implementations of activities)
  • service [android library] (no coverage) -> depends on commons, service-test-support
  • app [android application] no tests

For the context of this posts, I'm only interested in unit tests

The tests run as expected however no coverage is generated due to a SOME (not all) of the kotlin compiled classes being recognised as "instrumented classes"

The errors appear just as the tests are about to being where the following is printed out for many classes:

    java.lang.instrument.IllegalClassFormatException: Error while instrumenting com/github/goldy1992/mp3player/client/views/viewholders/MediaPlayerTrackViewHolder.
        at org.jacoco.agent.rt.internal_035b120.CoverageTransformer.transform(CoverageTransformer.java:93)
        at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
        at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.getDeclaredFields0(Native Method)
        at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
        at java.lang.Class.getDeclaredFields(Class.java:1916)
        at org.junit.runners.model.TestClass.getSortedDeclaredFields(TestClass.java:77)
        at org.junit.runners.model.TestClass.scanAnnotatedMembers(TestClass.java:70)
        at org.junit.runners.model.TestClass.<init>(TestClass.java:57)
        at org.junit.runners.ParentRunner.createTestClass(ParentRunner.java:88)
        at org.junit.runners.ParentRunner.<init>(ParentRunner.java:83)
        at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
        at org.robolectric.internal.SandboxTestRunner.<init>(SandboxTestRunner.java:71)
        at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:101)
        at org.robolectric.RobolectricTestRunner.<init>(RobolectricTestRunner.java:96)
        at sun.reflect.GeneratedConstructorAccessor5.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
        at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder$DefensiveAnnotatedBuilder.buildRunner(DefensiveAllDefaultPossibilitiesBuilder.java:113)
        at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
        at org.junit.vintage.engine.discovery.DefensiveAllDefaultPossibilitiesBuilder.runnerForClass(DefensiveAllDefaultPossibilitiesBuilder.java:56)
        at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
        at org.junit.vintage.engine.discovery.TestClassRequestResolver.createRunnerTestDescriptor(TestClassRequestResolver.java:55)
        at org.junit.vintage.engine.discovery.VintageDiscoverer.lambda$discover$0(VintageDiscoverer.java:53)
        at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
        at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
        at java.util.Iterator.forEachRemaining(Iterator.java:116)
        at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
        at java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:742)
        at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
        at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
        at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
        at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
        at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
        at org.junit.vintage.engine.discovery.VintageDiscoverer.discover(VintageDiscoverer.java:55)
        at org.junit.vintage.engine.VintageTestEngine.discover(VintageTestEngine.java:62)
        at org.junit.platform.launcher.core.DefaultLauncher.discoverEngineRoot(DefaultLauncher.java:168)
        at org.junit.platform.launcher.core.DefaultLauncher.discoverRoot(DefaultLauncher.java:155)
        at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:128)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:102)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:82)
        at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:78)
        at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
        at com.sun.proxy.$Proxy2.stop(Unknown Source)
        at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:132)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
        at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
        at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
        at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:412)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
        at java.lang.Thread.run(Thread.java:748)
    Caused by: java.io.IOException: Error while instrumenting com/github/goldy1992/mp3player/client/views/viewholders/MediaPlayerTrackViewHolder.
        at org.jacoco.agent.rt.internal_035b120.core.instr.Instrumenter.instrumentError(Instrumenter.java:158)
        at org.jacoco.agent.rt.internal_035b120.core.instr.Instrumenter.instrument(Instrumenter.java:108)
        at org.jacoco.agent.rt.internal_035b120.CoverageTransformer.transform(CoverageTransformer.java:91)
        ... 86 more
    Caused by: java.lang.IllegalStateException: Cannot process instrumented class com/github/goldy1992/mp3player/client/views/viewholders/MediaPlayerTrackViewHolder. Please supply original non-instrumented classes.
        at org.jacoco.agent.rt.internal_035b120.core.internal.instr.InstrSupport.assertNotInstrumented(InstrSupport.java:237)
        at org.jacoco.agent.rt.internal_035b120.core.internal.instr.ClassInstrumenter.visitField(ClassInstrumenter.java:55)
        at org.jacoco.agent.rt.internal_035b120.asm.ClassVisitor.visitField(ClassVisitor.java:287)
        at org.jacoco.agent.rt.internal_035b120.asm.ClassReader.readField(ClassReader.java:906)
        at org.jacoco.agent.rt.internal_035b120.asm.ClassReader.accept(ClassReader.java:683)
        at org.jacoco.agent.rt.internal_035b120.asm.ClassReader.accept(ClassReader.java:400)
        at org.jacoco.agent.rt.internal_035b120.core.instr.Instrumenter.instrument(Instrumenter.java:88)
        at org.jacoco.agent.rt.internal_035b120.core.instr.Instrumenter.instrument(Instrumenter.java:106)
        ... 87 more

To try and get to the root of the problem I am just running the client unit tests

Client build.gradle

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'de.mannodermaus.android-junit5'
apply plugin: 'jacoco'

android {

    compileSdkVersion TARGET_SDK_VERION
    buildToolsVersion BUILD_TOOLS_VERSION

    defaultConfig {
        minSdkVersion MIN_SDK_VERSION
        targetSdkVersion TARGET_SDK_VERION
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        consumerProguardFiles 'consumer-rules.pro'
        vectorDrawables.useSupportLibrary = true
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            debuggable true
            minifyEnabled false
            testCoverageEnabled = true
        }
    }
    flavorDimensions 'default'
    productFlavors {
        full {
            dimension = 'default'
        }
        automation {
            dimension = 'default'
        }
    }

    compileOptions {
        incremental = false
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions { jvmTarget = "1.8" }


    testOptions {
        execution 'ANDROID_TEST_ORCHESTRATOR'
        animationsDisabled true

        unitTests {
            includeAndroidResources = true
            returnDefaultValues = true
        }

        unitTests.all {
            testLogging {
                events "passed", "skipped", "failed", "standardOut", "standardError"
                outputs.upToDateWhen {false}
                showStandardStreams = true
            }
        }
    }

    sourceSets {
        main.java.srcDirs += 'src/main/java'
        test.java.srcDirs += 'src/test/java'
        androidTest.java.srcDirs += 'src/androidTest/java'
    }
}

dependencies {
 implementation project(path: ':commons')
 testApi project(":client:testsupport")

 /* MORE DEPENDENCIES NOT RELEVANT TO ISSUE */
}

It may be worth noting that I am using Dagger 2.25.2

Execution data dir: ${projectRootDir}/client/build/jacoco/testFullDebugUnitTest.exec

Source dir: ${projectRootDir}/client/src/main/java

class dir: ${projectRootDir}/client/build/intermediates/javac/fullDebug/classes/, ${projectRootDir}/client/build/tmp/kotlin-classes/fullDebug/

UPDATE 1: From making a new branch and and renaming all the classes and test classes in the client module to CLASS_NAME.kt.old I can confirm that there seems to be no connection between the IllegalClassFormatException and the no coverage.I will therefore update the questions to be the following

UPDATE 2: After further experimenting with update 1 it seems that the exceptions go away and coverage is calculated as expected WHEN there is no dependency on the sub (test) module, i.e. remove the line testApi project(":client:testsupport")from the gradle file. The problem is that I need this testsupportmodule in order to execute my activity tests (which are currently not run because they are in a .old file as per update 1 ^^.

Questions updated as per udate 2 How can I configure JaCoCo to support sub module test implementation of android classes as suggested by the robolectric team in this pull request.

Will update post if more information is required


回答1:


I just faced the same bug.

After a little investigation, it seems like it is a bug in the Android Gradle Plugin, and it only happens when using com.android.library.

I have reported it and more details here: https://issuetracker.google.com/issues/178015739

While it isn't fixed by the Android team, a workaround is to configure

jacoco {
    toolVersion = "0.7.9"
}

in the build.gradle

It doesn't prevent the error from being logged, but makes it so that the coverage data is collected properly.



来源:https://stackoverflow.com/questions/59378618/kotlin-jacoco-no-coverage-illegalclassformatexception-please-supply-orig

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!