plugin-under-test-metadata.properties在IDEA中运行测试时不是由Gradle TestKit创建的
我正在使用Gradle3.3,并试图用JUnit和GradleTestKit测试一个自定义插件。在plugin的build.gradle中 测试是plugin-under-test-metadata.properties在IDEA中运行测试时不是由Gradle TestKit创建的,gradle,gradle-plugin,Gradle,Gradle Plugin,我正在使用Gradle3.3,并试图用JUnit和GradleTestKit测试一个自定义插件。在plugin的build.gradle中 测试是 package com.huawei.odmf.codegen.gradle import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner import org.gradle.testkit.runner.TaskOutcome
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
}
}
这似乎是automaticClasspathInjectionQuickstart示例所需的全部内容
但是,该测试在withPluginClasspath编辑时失败:在IDEA中运行时;据我所知,它从命令行开始使用以下堆栈跟踪,plugin-under-test-metadata.properties应该由java gradle插件自动创建:
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)
我遗漏了什么?在确定问题仅在IDEA中出现后,我发现并添加了
plugins {
id "com.palantir.idea-test-fix" version "0.1.0"
}
转到插件子项目的build.gradle的开头。它解决了这个问题
在中,我找到了另一个解决方案:在设置->构建->构建工具->渐变->运行程序中,选择渐变测试运行程序而不是平台测试运行程序,然后在再次运行之前删除测试的运行/调试配置
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,也可能适用于早期版本
这利用了在每次构建之前执行pluginUnderTestMetadata和自定义fixIdeaPluginClasspath,后者将仅从IDEA内部运行,而不是在运行本机gradle时
第一个任务——pluginUnderTestMetadata——确保创建属性文件,并由本机Gradle执行
第二个任务——fixidapluginclasspath——修复了IDEA执行测试的另一个bug:由pluginUnderTestMetadata生成的类路径将只包含对$projectDir/build目录的引用,IDEA不会在该目录中输出其编译的类;因此,您不会看到IDEA编译的插件代码中所做的更改,而只会看到native gradle编译的插件代码。然后,它所做的是将IDEA classes目录前置到classpath。起初,我还尝试删除$projectDir/build引用,但是gradle不喜欢它抱怨插件名称空间问题,这对我来说太巫毒了
感谢您在前面的回答中指出pluginUnderTestMetadata。在Gradle4中,我试图使用gradleTestKit,但出现了此错误 添加下面的插件修复了它。
这可能是由于测试之前未执行pluginUnderTestMetadata造成的。这就是生成元数据的原因,您的执行正在抱怨元数据 解决此问题的一种方法是将该任务添加为测试要求: tasks.withType{ dependsOnpluginUnderTestMetadata } 一些测试执行者在执行测试之前可能无法捕捉到这一点。作为一种解决方法,您可以在编译测试类时依赖于此: tasks.namedTestClass{ dependsOnpluginUnderTestMetadata }
据我所知,您不需要显式调用pluginclasspath。不要显式地调用它。如果有效,请告诉我,然后我给出一个答案。@Vampire不幸的是,它没有:插件[id:'com.huawei.odmf']在以下任何一个中都没有找到sources@Vampire它在命令行中也不起作用,但事实证明使用pluginclasspath调用的版本确实起作用。啊,好吧,很有趣。不幸的是,该插件的repo被删除或私有。是的,这是不幸的。我也无法切换到4.0并检查问题是否仍然存在,因此我不知道是否应该向Gradle报告错误。IntelliJ 2017.2也存在同样的问题。我无法让com.palantir.idea-test-fix正常工作,但是改变为gradle测试运行者的技巧非常有效!顺便说一句,这个问题发生在我尝试使用这里记录的vanilla gradle插件示例时:IDEA 2017.2.5和gradle 4.3仍然存在问题。更改跑步者并删除跑步配置修复了它,谢谢!所描述的解决方案并没有解决我的问题,但运行./gradlew pluginUnderTestMetadata解决了问题。在IDEA 2020.2中,唯一的解决方法是进入设置>构建>渐变>您的项目>使用并选择渐变默认运行测试。我还为他们打开了一个错误:同意,我在没有上述行的情况下使用渐变测试工具包时遇到了相同的错误,当我搜索谷歌时,我找到了你的问题。我知道StackOverflow不喜欢不相关的答案,所以我们真的无法回答次要问题:这确实是正确的答案:
plugins {
id "com.palantir.idea-test-fix" version "0.1.0"
}
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
}
}
plugins {
id 'java-gradle-plugin'
}