Kotlin / kotlinx-kover

Apache License 2.0
1.25k stars 46 forks source link

Cannot create tests for convention plugin with pre-configuring kover #560

Closed alosdev closed 2 months ago

alosdev commented 2 months ago

Describe the bug When the kover gradle plugin is pre-configured in my custom gradle plugin, I cannot make a successful test run.

Errors

org.gradle.api.internal.plugins.PluginApplicationException: Failed to apply plugin class 'kotlinx.kover.gradle.plugin.KoverGradlePlugin'.
    at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:176)
    at org.gradle.api.internal.plugins.DefaultPluginManager.addImperativePlugin(DefaultPluginManager.java:91)
    at org.gradle.api.internal.plugins.DefaultPluginManager.addImperativePlugin(DefaultPluginManager.java:98)
    at org.gradle.api.internal.plugins.DefaultPluginContainer.apply(DefaultPluginContainer.java:77)
    at com.github.alosdev.KoverConventionPlugin.apply(KoverConventionPlugin.kt:10)
    at com.github.alosdev.KoverConventionPlugin.apply(KoverConventionPlugin.kt:7)
    at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)
    at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:51)
    at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:190)
    at org.gradle.api.internal.plugins.DefaultPluginManager.access$100(DefaultPluginManager.java:54)
    at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:285)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
    at org.gradle.api.internal.plugins.DefaultPluginManager.lambda$doApply$0(DefaultPluginManager.java:170)
    at org.gradle.internal.code.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:43)
    at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:169)
    at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:148)
    at com.github.alosdev.KoverConventionPluginTest.createProject(KoverConventionPluginTest.kt:35)
    at com.github.alosdev.KoverConventionPluginTest.kotlin plugin get applied(KoverConventionPluginTest.kt:16)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.gradle.api.reflect.ObjectInstantiationException: Could not create an instance of type kotlinx.kover.gradle.plugin.dsl.internal.KoverReportExtensionImpl.
    at org.gradle.internal.instantiation.generator.DependencyInjectingInstantiator.doCreate(DependencyInjectingInstantiator.java:69)
    at org.gradle.internal.instantiation.generator.DependencyInjectingInstantiator.newInstanceWithDisplayName(DependencyInjectingInstantiator.java:50)
    at org.gradle.internal.extensibility.DefaultConvention.instantiate(DefaultConvention.java:233)
    at org.gradle.internal.extensibility.DefaultConvention.create(DefaultConvention.java:142)
    at kotlinx.kover.gradle.plugin.appliers.ProjectApplier.onApply(ProjectApplier.kt:157)
    at kotlinx.kover.gradle.plugin.KoverGradlePlugin.apply(KoverGradlePlugin.kt:33)
    at kotlinx.kover.gradle.plugin.KoverGradlePlugin.apply(KoverGradlePlugin.kt:24)
    at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)
    at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:51)
    at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:190)
    at org.gradle.api.internal.plugins.DefaultPluginManager.access$100(DefaultPluginManager.java:54)
    at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:285)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
    at org.gradle.api.internal.plugins.DefaultPluginManager.lambda$doApply$0(DefaultPluginManager.java:170)
    at org.gradle.internal.code.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:43)
    at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:169)
    ... 27 more
Caused by: java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/ActionExtensionsKt
    at kotlinx.kover.gradle.plugin.dsl.internal.KoverReportsConfigImpl.xml(KoverReportExtension.kt:90)
    at kotlinx.kover.gradle.plugin.appliers.AppliersCommonsKt.defaultReports(AppliersCommons.kt:20)
    at kotlinx.kover.gradle.plugin.dsl.internal.KoverReportExtensionImpl.<init>(KoverReportExtension.kt:26)
    at kotlinx.kover.gradle.plugin.dsl.internal.KoverReportExtensionImpl_Decorated.<init>(Unknown Source)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at org.gradle.internal.instantiation.generator.AsmBackedClassGenerator$InvokeConstructorStrategy.newInstance(AsmBackedClassGenerator.java:2097)
    at org.gradle.internal.instantiation.generator.AbstractClassGenerator$GeneratedClassImpl$GeneratedConstructorImpl.newInstance(AbstractClassGenerator.java:526)
    at org.gradle.internal.instantiation.generator.DependencyInjectingInstantiator.doCreate(DependencyInjectingInstantiator.java:64)
    ... 49 more
Caused by: java.lang.ClassNotFoundException: org.gradle.kotlin.dsl.ActionExtensionsKt
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    ... 61 more

Could not create an instance of type kotlinx.kover.gradle.plugin.dsl.internal.KoverReportExtensionImpl.
org.gradle.api.reflect.ObjectInstantiationException: Could not create an instance of type kotlinx.kover.gradle.plugin.dsl.internal.KoverReportExtensionImpl.
    at org.gradle.internal.instantiation.generator.DependencyInjectingInstantiator.doCreate(DependencyInjectingInstantiator.java:69)
    at org.gradle.internal.instantiation.generator.DependencyInjectingInstantiator.newInstanceWithDisplayName(DependencyInjectingInstantiator.java:50)
    at org.gradle.internal.extensibility.DefaultConvention.instantiate(DefaultConvention.java:233)
    at org.gradle.internal.extensibility.DefaultConvention.create(DefaultConvention.java:142)
    at kotlinx.kover.gradle.plugin.appliers.ProjectApplier.onApply(ProjectApplier.kt:157)
    at kotlinx.kover.gradle.plugin.KoverGradlePlugin.apply(KoverGradlePlugin.kt:33)
    at kotlinx.kover.gradle.plugin.KoverGradlePlugin.apply(KoverGradlePlugin.kt:24)
    at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)
    at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:51)
    at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:190)
    at org.gradle.api.internal.plugins.DefaultPluginManager.access$100(DefaultPluginManager.java:54)
    at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:285)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
    at org.gradle.api.internal.plugins.DefaultPluginManager.lambda$doApply$0(DefaultPluginManager.java:170)
    at org.gradle.internal.code.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:43)
    at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:169)
    at org.gradle.api.internal.plugins.DefaultPluginManager.addImperativePlugin(DefaultPluginManager.java:91)
    at org.gradle.api.internal.plugins.DefaultPluginManager.addImperativePlugin(DefaultPluginManager.java:98)
    at org.gradle.api.internal.plugins.DefaultPluginContainer.apply(DefaultPluginContainer.java:77)
    at com.github.alosdev.KoverConventionPlugin.apply(KoverConventionPlugin.kt:10)
    at com.github.alosdev.KoverConventionPlugin.apply(KoverConventionPlugin.kt:7)
    at org.gradle.api.internal.plugins.ImperativeOnlyPluginTarget.applyImperative(ImperativeOnlyPluginTarget.java:43)
    at org.gradle.api.internal.plugins.RuleBasedPluginTarget.applyImperative(RuleBasedPluginTarget.java:51)
    at org.gradle.api.internal.plugins.DefaultPluginManager.addPlugin(DefaultPluginManager.java:190)
    at org.gradle.api.internal.plugins.DefaultPluginManager.access$100(DefaultPluginManager.java:54)
    at org.gradle.api.internal.plugins.DefaultPluginManager$AddPluginBuildOperation.run(DefaultPluginManager.java:285)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
    at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
    at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
    at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
    at org.gradle.api.internal.plugins.DefaultPluginManager.lambda$doApply$0(DefaultPluginManager.java:170)
    at org.gradle.internal.code.DefaultUserCodeApplicationContext.apply(DefaultUserCodeApplicationContext.java:43)
    at org.gradle.api.internal.plugins.DefaultPluginManager.doApply(DefaultPluginManager.java:169)
    at org.gradle.api.internal.plugins.DefaultPluginManager.apply(DefaultPluginManager.java:148)
    at com.github.alosdev.KoverConventionPluginTest.createProject(KoverConventionPluginTest.kt:35)
    at com.github.alosdev.KoverConventionPluginTest.kotlin plugin get applied(KoverConventionPluginTest.kt:16)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: java.lang.NoClassDefFoundError: org/gradle/kotlin/dsl/ActionExtensionsKt
    at kotlinx.kover.gradle.plugin.dsl.internal.KoverReportsConfigImpl.xml(KoverReportExtension.kt:90)
    at kotlinx.kover.gradle.plugin.appliers.AppliersCommonsKt.defaultReports(AppliersCommons.kt:20)
    at kotlinx.kover.gradle.plugin.dsl.internal.KoverReportExtensionImpl.<init>(KoverReportExtension.kt:26)
    at kotlinx.kover.gradle.plugin.dsl.internal.KoverReportExtensionImpl_Decorated.<init>(Unknown Source)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at org.gradle.internal.instantiation.generator.AsmBackedClassGenerator$InvokeConstructorStrategy.newInstance(AsmBackedClassGenerator.java:2097)
    at org.gradle.internal.instantiation.generator.AbstractClassGenerator$GeneratedClassImpl$GeneratedConstructorImpl.newInstance(AbstractClassGenerator.java:526)
    at org.gradle.internal.instantiation.generator.DependencyInjectingInstantiator.doCreate(DependencyInjectingInstantiator.java:64)
    ... 49 more
Caused by: java.lang.ClassNotFoundException: org.gradle.kotlin.dsl.ActionExtensionsKt
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
    ... 61 more

> Task :plugin-build:jvm:test FAILED
KoverConventionPluginTest > kotlin plugin get applied() FAILED
    org.gradle.api.internal.plugins.PluginApplicationException at KoverConventionPluginTest.kt:35
        Caused by: org.gradle.api.reflect.ObjectInstantiationException at KoverConventionPluginTest.kt:35
            Caused by: java.lang.NoClassDefFoundError at KoverConventionPluginTest.kt:35
                Caused by: java.lang.ClassNotFoundException at KoverConventionPluginTest.kt:35
1 test completed, 1 failed
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':plugin-build:jvm:test'.
> There were failing tests. See the report at: file:///Users/A200289886/source/tsi/dv/dv-core/dv-gradle-plugins/plugin-build/jvm/build/reports/tests/test/index.html
* Try:
> Run with --scan to get full insights.
BUILD FAILED in 2s

Expected behavior test runs successfully

Reproducer custom convention Plugin:

package com.github.alosdev

import kotlinx.kover.gradle.plugin.KoverGradlePlugin
import org.gradle.api.Plugin
import org.gradle.api.Project

public abstract class KoverConventionPlugin : Plugin<Project> {
    public override fun apply(project: Project): Unit =
        with(project) {
            plugins.apply(KoverGradlePlugin::class.java)
        }
}

the test for the plugin:

package com.github.alosdev

import org.gradle.api.Project
import org.gradle.testfixtures.ProjectBuilder
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import java.io.File

internal class KoverConventionPluginTest {
    @field:TempDir
    private lateinit var tempDir: File

    @Test
    fun `kotlin plugin get applied`() {
        val project = createProject()

        Assertions.assertTrue(project.pluginManager.hasPlugin("kover-gradle-plugin"))
    }

    private fun createProject(): Project {
        return ProjectBuilder.builder()
            .withProjectDir(tempDir)
            .withName("dummy")
            .build()
            .also {
                it.pluginManager.apply("com.github.alosdev.convention.kover")
            }
    }
}

Environment

Note My wild guess is that the implementation is internal instead of public.

shanshin commented 2 months ago

Hi, in this place function operator fun <T> Action<in T>.invoke(target: T) = execute(target) from org.gradle.gradle.kotlin-dsl is used. Please try to apply kotlin-dsl plugin in your convention plugin

alosdev commented 2 months ago

hmm. that means I have to rewrite my custom plugins so I could make it testable... As this is just a tiny part of my plugin.
I have to think about how to make it kotlin-dsl compatible in some parts or extracting the kover part in an own custom convention plugin.

shanshin commented 2 months ago

Alternatively, you can add kotlin-dsl to the classpath of ProjectBuilder

alosdev commented 2 months ago

thanks for the hint. Adding this to the dependencies helped

    testRuntimeOnly(gradleKotlinDsl())