【问题标题】:Only run task if another isn't UP-TO-DATE in gradle只有在另一个不是 UP-TO-DATE 时才运行任务
【发布时间】:2015-01-16 22:29:19
【问题描述】:

我想在 Gradle 中做功能测试时自动添加一个 serverRun 任务,所以我添加了一个依赖:

funcTestTask.dependsOn(serverRun)

无论 funcTestTask 是否运行,这都会导致任务运行

:compile
:serverRun
:funcTestTask (and associate compile tasks... etc)
:serverStop

OR

:compile UP-TO-DATE
:serverRun <-- unnecessary 
:funcTestTask UP-TO-DATE
:serverStop

启动服务器的成本非常高,我只希望它在功能测试 不是 UP-TO-DATE、我想做或其他事情时启动:

if(!funcTestTask.isUpToDate) {
    funcTestTask.dependsOn(serverRun)
}

所以我知道在确定它的所有输入/输出之前我无法知道 funcTestTask 的最新状态但是我可以继承它的 uptoDate 检查器吗?

serverRun.outputs.upToDateWhen(funcTestTask.upToDate)

替代方法是在 FuncTest 中“doFirst”ServerRun,我认为这通常是不受欢迎的?

funcTestTask.doFirst { serverRun.execute() }

有没有办法在另一个任务之前有条件地运行一个任务?

更新 1
尝试设置输入/输出相同

serverRun.inputs.files(funcTestTask.inputs.files)
serverRun.outputs.files(funcTestTask.outputs.files)

这似乎在重新编译时重新运行服务器(好),在成功的未更改功能测试后跳过重新运行(也很好),但在测试失败后不会重新运行测试,如下所示

:compile
:serverRun
:funcTestTask FAILED

then

:compile UP-TO-DATE
:serverRun UP-TO-DATE <-- wrong!
:funcTestTask FAILED

【问题讨论】:

  • 您可以通过简单地使他们的输入相同来有效地模拟这一点。我假设funcTestTaskTest 类型的一些任务?还必须有一些任务来编译这些测试?
  • 是的,它是Test类型。但是,如果测试失败,该信息会缓存在哪里?因为输入保持不变,但之前的任务失败了
  • 您可以轻松检查任务是否失败。表达式task.state.failure == null 将是true 用于成功执行任务。
  • 但是只有在测试运行后才能知道成功。我想要的是检查任务是否在以前的运行中失败(这会影响最新状态)。
  • 在使用 Gradle -i 参数运行失败的测试套件时,它表示由于输出目录的更改而导致最新检查失败。也许添加test.binResultsDir 作为输出目录?

标签: gradle task


【解决方案1】:

遇到同样的问题后,我找到了一个非常干净的解决方案。就我而言,我希望在运行构建时生成一个 Eclipse 项目设置,但仅在生成新 jar 时生成。当 jar 是最新的时,不应执行任何项目设置。以下是实现这一目标的方法:

tasks.eclipse {
  onlyIf {
    !jar.state.upToDate
  }
}

build {
  dependsOn tasks.eclipse
}

【讨论】:

  • 这似乎对我不起作用。 state.upToDate 总是返回 false,即使该任务实际上后来被认为是最新的。
  • 对我来说也一样,执行 onlyIf 时状态尚未设置
【解决方案2】:

我最终写入了一个“故障文件”并将其作为 serverRun 任务的输入:

File serverTrigger = project.file("${buildDir}/trigger") 

project.gradle.taskGraph.whenReady { TaskExecutionGraph taskGraph ->
  // make the serverRun task have the same inputs/outputs + extra trigger
  serverRun.inputs.files(funcTestTask.inputs.files, serverTrigger)
  serverRun.outputs.files(funcTestTask.outputs.files)
}

project.gradle.taskGraph.afterTask { Task task, TaskState state ->
  if (task.name == "funcTestTask" && state.failure) {
    serverRun.trigger << new Date()
  }
}

根据我在 Gradle 论坛上的问题的答案提供的信息: http://forums.gradle.org/gradle/topics/how-can-i-start-a-server-conditionally-before-a-functionaltestrun

【讨论】:

    【解决方案3】:

    由于任务是您尝试控制的任务的依赖任务,因此您可以尝试:

    tasks {
        onlyIf {
            dependsOnTaskDidWork()
        }
    }
    

    【讨论】:

    • 这个对我有用:只是 dependsOnTaskDidWork 已弃用,但可以用 task.didWork 替换
    【解决方案4】:

    我遇到了同样的问题,但我想出的解决方案要简单得多。 只有在需要测试时才会启动服务器

    test {
        doFirst {
            exec {
                executable = 'docker/_ci/run.sh'
                args = ['--start']
            }
        }
    
        doLast {
            exec {
                executable = 'docker/_ci/run.sh'
                args = ['--stop']
            }
        }
    }
    

    【讨论】:

      【解决方案5】:

      假设您有task1task2,它们依赖于task1,并且只有在task1 不是最新的情况下才需要运行task2,可以使用以下示例:

      task task1 {
        // task1 definition
      }
      
      task task2(dependsOn: task1) {
        onlyIf { task1.didWork }
      }
      

      在这种情况下,task2 将仅在 task1 不是最新的情况下运行。重要的是仅将didWork 用于dependsOn 中定义的任务,以确保在该任务(在我们的示例中为task1)有机会运行之后评估didWork

      【讨论】:

        猜你喜欢
        • 2011-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多