在IDEA中运行测试时,不是由Gradle TestKit创建的plugin-under-test-metadata.properties

时间:2017-06-21 14:31:03

标签: gradle gradle-plugin

我正在使用Gradle 3.3并尝试使用JUnit和Gradle TestKit测试自定义插件。在插件的build.gradle我有

version '0.1'

apply plugin: 'groovy'
apply plugin: 'java-gradle-plugin'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile project(':codegen-core')
    compile localGroovy()
    testCompile 'junit:junit:4.12'
}

测试

package com.huawei.odmf.codegen.gradle

import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder

import static org.junit.Assert.*

class TestOdmfCodegenPlugin {

    @Rule 
    public final TemporaryFolder testProjectDir = new TemporaryFolder()

    private File buildFile
    private File assetsDir

    @Before
    void setUp() {
        buildFile = testProjectDir.newFile("build.gradle")
        assetsDir = testProjectDir.newFolder("src", "main", "assets")
    }

    @Test
    void testPlugin() {
        buildFile << """
          plugins {
          id 'com.huawei.odmf'
        }

        apply plugin: 'com.android.application'

        odmf {
            modelFile 'odmf.xml'
        }
        """

        BuildResult result = GradleRunner.create().
                withProjectDir(testProjectDir.root).
                withArguments(OdmfCodegenPlugin.taskName).
                withPluginClasspath().
                build()

        // assertions
    }
}

src/main/resources/META-INF/gradle-plugins/com.huawei.odmf.properties下我有

implementation-class=com.huawei.odmf.codegen.gradle.OdmfCodegenPlugin

根据https://docs.gradle.org/current/userguide/test_kit.html#sub:test-kit-automatic-classpath-injectionautomaticClasspathInjectionQuickstart样本,这似乎都是必需的。

但是,此测试在withPluginClasspath()(编辑:在IDEA中运行;它在命令行中运行)时失败,并带有以下堆栈跟踪(根据我的理解,plugin-under-test-metadata.properties应由{创建java-gradle-plugin自动{1}}:

org.gradle.testkit.runner.InvalidPluginMetadataException: Test runtime classpath does not contain plugin metadata file 'plugin-under-test-metadata.properties'

    at org.gradle.testkit.runner.internal.PluginUnderTestMetadataReading.readImplementationClasspath(PluginUnderTestMetadataReading.java:44)
    at org.gradle.testkit.runner.internal.PluginUnderTestMetadataReading.readImplementationClasspath(PluginUnderTestMetadataReading.java:37)
    at org.gradle.testkit.runner.internal.DefaultGradleRunner.withPluginClasspath(DefaultGradleRunner.java:146)
    at org.gradle.testkit.runner.internal.DefaultGradleRunner$withPluginClasspath$0.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
    at com.huawei.odmf.codegen.gradle.TestOdmfCodegenPlugin.testPlugin(TestOdmfCodegenPlugin.groovy:40)
    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:497)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

我错过了什么?

4 个答案:

答案 0 :(得分:15)

在确定问题仅在IDEA中之后,我发现了https://plugins.gradle.org/plugin/com.palantir.idea-test-fix并添加了

plugins {
  id "com.palantir.idea-test-fix" version "0.1.0"
}

到插件子项目的build.gradle的开头。它解决了这个问题。

this post (Russian)中,我找到了另一种解决方案:在Settings-> Build-> Build Tools->Gradle->Runner中,选择Gradle Test Runner而不是Platform Test Runner,然后在运行前删除测试的运行/调试配置再一次。

答案 1 :(得分:3)

在Gradle 4中,我尝试使用gradleTestKit()并收到此错误。

  • 添加以下插件对其进行了修复。
plugins {
    id 'java-gradle-plugin'
}

答案 2 :(得分:1)

plugins {
    id "org.jetbrains.gradle.plugin.idea-ext" version "0.4.2"
}

task fixIdeaPluginClasspath {
    doFirst {
        configure(tasks.pluginUnderTestMetadata) {
            def ideaClassesPath = project.buildDir.toPath().resolveSibling("out").resolve("production")
            def newClasspath = pluginClasspath as List
            newClasspath.add(0, ideaClassesPath)
            pluginClasspath.setFrom(newClasspath)
        }
    }
}
pluginUnderTestMetadata.mustRunAfter(fixIdeaPluginClasspath)

idea.project.settings {
    taskTriggers {
        beforeBuild fixIdeaPluginClasspath, pluginUnderTestMetadata
    }
}

此功能可与IDEA 2019.1配合使用(并且也可以与较早的版本配合使用)。

这利用JetBrains' own gradle plugin for configuring IDEA settings在每次构建之前执行pluginUnderTestMetadata和自定义fixIdeaPluginClasspath(后者仅从IDEA内部运行,而不是在运行本机gradle时)。

第一个任务pluginUnderTestMetadata –确保创建属性文件,并且也由本机Gradle执行。

第二项任务fixIdeaPluginClasspath修复了IDEA如何执行测试的另一个错误:由pluginUnderTestMetadata生成的类路径将仅包含对"$projectDir/build"目录的引用, IDEA输出其编译的类;因此,您将不会看到在IDEA编译的插件代码中所做的更改,而只会看到由本地gradle编译的更改。然后要做的是将IDEA classes目录添加到classpath之前。最初,我还尝试删除了"$projectDir/build"参考,但是gradle然后不喜欢它抱怨插件名称空间问题(对我来说太巫毒了)。

感谢@krzychu指出pluginUnderTestMetadata(在先前的回答中)。

答案 3 :(得分:0)

这可能是由于在测试之前没有执行pluginUnderTestMetadata而导致的。这就是生成元数据的原因,您的执行过程会对此抱怨。

解决此问题的一种方法是将任务添加为测试的要求:

tasks.withType<Test> {
    dependsOn("pluginUnderTestMetadata")
}

一些测试执行者可能在执行测试之前就没有抓住这一点。作为解决方法,您可以在编译测试类时依赖它:

tasks.named("testClasses") {
    dependsOn("pluginUnderTestMetadata")
}