这个问题来自 Twitter 上的 Martin Grotzke .
他想写一个任务(或命令,我想),可以:
test
如果失败,请跟进 testOnly
有效地模拟 Bash:
$ sbt test || sbt testQuick
这样做的动机是运行两次失败的测试以解决不稳定的测试。
最佳答案
项目/TestExtraShotPlugin.scala
如果您想要快速回答,您可以使用以下代码来实现运行测试两次行为。
import sbt._
import Keys._
object TestExtraShotPlugin extends AutoPlugin {
override def requires = plugins.JvmPlugin
override def trigger = allRequirements
object autoImport {
val testNoFail = taskKey[Unit]("test but don't fail")
}
import autoImport._
override def buildSettings = {
addCommandAlias("testExtraShot", ";testNoFail;testQuick")
}
override def projectSettings = {
Test / testNoFail := (Test / test).result.value
}
}
如果您想了解更多,请继续阅读。
错误处理
首先,我们需要停止
test
从停止任务执行。 Tasks 中描述了任务的错误处理。文档的页面。但要点是您调用.result.value
.您可以对其进行模式匹配以获取值,但我们在这里并不需要它。我用它来定义一个替代
test
名为 testNoFail
的任务.临时插件
接下来,我们要
testNoFail
在多项目构建中工作。将设置注入(inject)所有子项目的一种方法是定义触发的 AutoPlugin
在 project/*.scala
. override def requires = plugins.JvmPlugin
override def trigger = allRequirements
命令组成
如果你想告诉 sbt 做某事 然后 做点别的,可能很自然的方式就是使用命令。这类似于人类连续向外壳输入内容。
命令可以使用分号
;
组成. override def buildSettings = {
addCommandAlias("testExtraShot", ";testNoFail;testQuick")
}
这是可能的,因为我们可以安全地运行
testQuick
task无论之前的测试状态如何。另见 Sequencing How to series 用于对事物进行排序的其他方法。
如何使用这个
跑:
> testExtraShot
在 sbt 外壳内。这将运行
testNoFail
然后 testQuick
.附录:处理有条件的延续
请注意,我通过运行
testQuick
绕过了 Martin 的“测试失败时”的原始规范。不管。可以实现这一点,但它更高级一些。一元延续
我们可以定义一个首先正常运行的任务
test
,然后根据返回的结果值,改变下一个任务的继续。在 sbt 中,这种类型的单子(monad)延续可以使用 dynamic task 来实现。 .我们通常会尽量避免这种组合,因为它会阻止任务引擎并行化并发任务,但是当我们需要 if-then-do-something 时它很方便。
project/TestExtraShotPlugin.scala 替代版本
以下实现了一个定义动态任务的临时插件:
import sbt._
import Keys._
object TestExtraShotPlugin extends AutoPlugin {
override def requires = plugins.JvmPlugin
override def trigger = allRequirements
object autoImport {
val testExtraShot = taskKey[Unit]("test then testQuick only on failure")
}
import autoImport._
override def projectSettings = {
testExtraShot := (Def.taskDyn {
val t = (Test / test).result.value
if (t.toEither.isLeft) (Test / testQuick).toTask("")
else
Def.task {
val s = streams.value
s.log.info("ok!")
}
}).value
}
}
关于scala - sbt:如何编写仅在测试失败时才运行 testQuick 的任务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51688743/