【问题标题】:Custom Gradle task running under nebula-test fails to see created directory在 nebula-test 下运行的自定义 Gradle 任务无法看到创建的目录
【发布时间】:2015-03-26 16:58:43
【问题描述】:

我有一个自定义 Gradle 插件的工作版本。我有几个单元测试,现在我正在尝试使用 nebula-test 进行集成测试。

我在集成测试中遇到了一个令人困惑的测试错误。我在使用 nebula-test 的方式上一定做错了。

我将展示完整的代码,但我将首先描述基本要素。

插件定义了一个扩展块,其中包含一些属性,其中一个是可以找到特定文件的文件路径。对于上下文,该属性名称称为“yangFilesRootDir”。

插件创建一个名为“YangGenerate”的自定义任务的实例。该任务有一个名为“yangFilesRootDir”的 File 类型的实例变量,该实例变量上有一个 @InputDirectory 注释。该任务还有其他实例变量,其中一些带有“@Input...”注释。

任务有一个“init”方法,在项目评估后从插件中调用。这会根据扩展块中的值初始化任务实例变量。在“init”方法中,如果扩展块中没有设置“yangFilesRootDir”属性,我使用默认值“src/main/yang”。

在进行此集成测试之前,我设置了一个引用该插件的独立项目。该项目的“build.gradle”指定了扩展块,并且我已经使用属性设置和不使用属性设置对其进行了测试(我将文件存储在默认位置),它工作正常。

这就是我的规范现在的样子:

class YangPluginIntegSpec extends IntegrationSpec {
def 'simple'() {
    createFile("src/main/yang/dummy")
    writeHelloWorld("com.example")
    buildFile << applyPlugin(YangPlugin)
    buildFile << '''
        yang {
            yangFilesRootDir 'src/main/yang'
        }
    '''.stripIndent()

    when:
    ExecutionResult result = runTasksSuccessfully('build')

    then:
    println result
}

}

我在有和没有“yang”块的情况下都试过了,但这个堆栈跟踪测试失败了:

org.gradle.api.GradleException: Build aborted because of an internal error.
    at nebula.test.functional.internal.DefaultExecutionResult.rethrowFailure(DefaultExecutionResult.groovy:95)
    at nebula.test.IntegrationSpec.runTasksSuccessfully(IntegrationSpec.groovy:234)
    at com.att.opnfv.yang.gradle.YangPluginIntegSpec.simple(YangPluginIntegSpec.groovy:18)
Caused by: org.gradle.internal.exceptions.LocationAwareException: A problem was found with the configuration of task ':yangGenerate'.
    at org.gradle.initialization.DefaultExceptionAnalyser.transform(DefaultExceptionAnalyser.java:77)
    at org.gradle.initialization.MultipleBuildFailuresExceptionAnalyser.transform(MultipleBuildFailuresExceptionAnalyser.java:47)
    at org.gradle.initialization.StackTraceSanitizingExceptionAnalyser.transform(StackTraceSanitizingExceptionAnalyser.java:30)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:108)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:80)
    at org.gradle.tooling.internal.provider.BuildModelAction.run(BuildModelAction.java:43)
    at org.gradle.tooling.internal.provider.BuildModelAction.run(BuildModelAction.java:30)
    at org.gradle.tooling.internal.provider.ConfiguringBuildAction.run(ConfiguringBuildAction.java:119)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:36)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
    at org.gradle.tooling.internal.provider.DaemonBuildActionExecuter.execute(DaemonBuildActionExecuter.java:42)
    at org.gradle.tooling.internal.provider.DaemonBuildActionExecuter.execute(DaemonBuildActionExecuter.java:29)
    at org.gradle.tooling.internal.provider.LoggingBridgingBuildActionExecuter.execute(LoggingBridgingBuildActionExecuter.java:62)
    at org.gradle.tooling.internal.provider.LoggingBridgingBuildActionExecuter.execute(LoggingBridgingBuildActionExecuter.java:34)
    at org.gradle.tooling.internal.provider.ProviderConnection.run(ProviderConnection.java:107)
    at org.gradle.tooling.internal.provider.ProviderConnection.run(ProviderConnection.java:94)
    at org.gradle.tooling.internal.provider.DefaultConnection.getModel(DefaultConnection.java:149)
    at org.gradle.tooling.internal.consumer.connection.CancellableModelBuilderBackedModelProducer.produceModel(CancellableModelBuilderBackedModelProducer.java:58)
    at org.gradle.tooling.internal.consumer.connection.AbstractConsumerConnection.run(AbstractConsumerConnection.java:56)
    at org.gradle.tooling.internal.consumer.DefaultBuildLauncher$1.run(DefaultBuildLauncher.java:82)
    at org.gradle.tooling.internal.consumer.DefaultBuildLauncher$1.run(DefaultBuildLauncher.java:76)
    at org.gradle.tooling.internal.consumer.connection.LazyConsumerActionExecutor.run(LazyConsumerActionExecutor.java:83)
    at org.gradle.tooling.internal.consumer.connection.ProgressLoggingConsumerActionExecutor.run(ProgressLoggingConsumerActionExecutor.java:58)
    at org.gradle.tooling.internal.consumer.async.DefaultAsyncConsumerActionExecutor$1$1.run(DefaultAsyncConsumerActionExecutor.java:55)
    at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
Caused by: org.gradle.api.tasks.TaskValidationException: A problem was found with the configuration of task ':yangGenerate'.
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:55)
    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
    at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:306)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
    ... 22 more
Caused by: org.gradle.api.InvalidUserDataException: Directory 'src\main\yang' specified for property 'yangFilesRootDir' does not exist.
    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:47)
    ... 41 more

我还用“-i”运行了它,以便获得更多信息,它向我显示了用于测试的临时构建目录的路径,并且在测试失败后我验证了“src/main/yang/dummy " 存在于测试项目目录中。

插件类的相关代码如下:

    class YangPlugin implements Plugin<Project> {
        public void apply(Project project) {
            YangExtension   yang  = project.extensions.create(YANG_EXT, YangExtension, project)
            YangGenerateTask  task  = project.task(YANG_GENERATE_TASK, type: YangGenerateTask)
            project.afterEvaluate {
                task.init(project, yang)
                project.compileJava.dependsOn task
                if (task.yangFilesRootDir && task.yangFilesRootDir.exists()) {
                    Jar jarTask = project.jar
                    if (task.yangFilesRootDir.getPath().startsWith(FilenameUtils.normalize(SRC_MAIN_RESOURCES))) {
                        jarTask.exclude(task.yangFilesRootDir.getPath() - FilenameUtils.normalize(SRC_MAIN_RESOURCES))
                    }
                    jarTask.from(task.yangFilesRootDir) { into(META_INF_YANG) }
                }
            }
        }
    }

以及YangGenerate任务的相关部分:

    class YangGenerateTask extends DefaultTask {
        private static final String DEFAULT_YANG_FILES_ROOT_DIR = "src/main/yang"   

        Project         project

        Collection<CodeGeneratorConfig> generators
        boolean                         inspectDependencies
        Collection<String>              excludeFiles
        String                          yangFilesConfiguration
        String                          generatorsConfiguration

        Pattern         yangFilePattern = Pattern.compile("META-INF/yang/.*\\.yang\$")

        @InputDirectory
        File    yangFilesRootDir

        @Input
        def getGeneratorClasses() {
            ...
        }

        @InputFiles
        def getOptionalYangClasspath() {
         ...
        }

        @OutputDirectories
        def getOutputDirectories() {
         ...
        }

        @TaskAction
        void generate() {
         ...
        }

        public void init(Project project, YangExtension yang) {
            this.yangFilesRootDir           = new File(yang.yangFilesRootDir ?: DEFAULT_YANG_FILES_ROOT_DIR)
            ...
        }
    }

更新

终于想到在调试器中运行这个测试,发现找不到路径的原因是“当前目录”不是测试项目的基目录,而是主目录的基目录插件项目,肯定没有“src/main/yang”目录。

【问题讨论】:

    标签: groovy gradle nebula-test


    【解决方案1】:

    #gradle 上的某个人向我指出了如何在插件代码中打开与项目 basedir (project.file(...)) 相关的文件,在我更改插件代码以执行此操作后,此错误消失了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-30
      • 2019-06-07
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 2020-07-09
      • 1970-01-01
      相关资源
      最近更新 更多