我将首先解释我的用例,然后是我想要做什么的概括描述。
默认 $gradle test
将运行 test
任务并运行所有单元测试。我想添加一个 browseTest
任务,如果在命令行中指定,它将在默认浏览器中打开测试报告。我已经有了打开测试结果的代码,但我需要弄清楚如何执行它。这是我认为它应该如何工作:
命令 | 最新测试 | 运行测试? | 测试结果? | 打开测试报告? |
---|---|---|---|---|
测试 | 没有 | 是的 | 成功/失败 | 没有 |
测试 | 是的 | 没有 | 成功/失败 | 没有 |
浏览测试 | 没有 | 是的 | 成功/失败 | 是的 |
浏览测试 | 是的 | 没有 | 成功/失败 | 是的 |
我希望能够让一项任务(即 browseTest
)向任务图中添加另一项任务(例如 task
),而不依赖于其他任务的成功或失败。如果我使用 dependsOn
,那么第一个失败会阻止第二个任务的执行。使用 mustRunAfter
指定排序但不将任务添加到任务图中(因此不会被执行)。
如果有类似下面的东西,我相信它会得到我想要的:
task("browseTest") {
addsToTaskGraph("test")
mustRunAfter("test")
doLast {
// Open test results in browser
}
}
答案 0 :(得分:0)
我再次回答了我自己的问题。我能够成功创建一个 runsAfter
扩展函数。我希望能够清理触发回调/挂钩的逻辑,但总体而言,这是非常用户友好的,并且不会过于低效。
val browseTest = task("browseTest") {
runsAfter(tasks.test.name) {
// perform "callback"
val file = project.file("build/reports/tests/test/index.html")
browse(file.absolutePath)
}
}
fun Task.runsAfter(vararg paths: String, action: () -> Unit) {
val parent = this
val helper = task("${name}__runsAfter") {
doLast {
if (gradle.taskGraph.hasTask(parent)) {
action()
}
}
}
paths.forEach {
dependsOn(it)
tasks[it].finalizedBy(helper)
}
}
虽然我不太喜欢这个结果,但我能够让它发挥作用。如果有人有任何其他想法,请告诉我。
val browseTest = task("browseTest") {
dependsOn("test")
val parent = this
val helper = task("browseTestHelper") {
doLast {
if (gradle.taskGraph.hasTask(parent)) {
// Open test results in browser
val file = project.file("build/reports/tests/test/index.html")
browse(file.absolutePath)
}
}
}
tasks.test {
finalizedBy(helper)
}
}
这里有几块:
browseTest
任务依赖于 test
,这意味着如果指定了 test
,它将强制运行。browseTest
任务实际上没有做任何事情。browseTestHelper
任务。test
任务配置为由 browseTestHelper
“完成”。browseTestHelper
运行时,它会检查原始 browseTest
任务是否在任务图中。如果没有,它不会做任何事情。
browseTestHelper
任务,也会创建 test
任务并完成 browseTest
。browseTest
在任务图中,它会执行其操作。有几种方法可以改进:
val parent = this
行之外,还有没有更好的方法来访问“父”任务?做这样的事情会很棒:
val browseTest = task("browseTest") {
runsAfter("test") {
val file = project.file("build/reports/tests/test/index.html")
browse(file.absolutePath)
}
}
答案 1 :(得分:0)
您自己的答案似乎很复杂。在我看来,您的问题的本质是在 test
将成为构建的一部分时不要让任务 browseTest
失败:
如果我使用 dependsOn
,那么第一个任务失败会阻止第二个任务的执行。
好吧,您可以简单地使用其 test
属性来防止任务 ignoreFailures
构建失败。将此属性与您的条件相结合,您就可以开始了。
我将在这里使用 Groovy 代码,因为我对 Gradle Kotlin DSL 不太熟悉:
test {
doFirst {
ignoreFailures = gradle.taskGraph.hasTask('browseTest')
}
}
task browseTest {
dependsOn 'test'
doLast {
// open in browser
}
}