这个问题来自Twitter上的马丁·格罗茨克(Martin Grotzke)。
他想写一个可以做的任务(或者说一个命令):
test
,如果失败,请继续执行testOnly
有效地模拟Bash:
$ sbt test || sbt testQuick
动机是运行两次失败的测试以解决不稳定的测试。
答案 0 :(得分:8)
如果您想获得快速解答,则可以使用以下代码来实现两次运行测试行为。
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
的{{1}}任务。
接下来,我们希望testNoFail
在多项目构建中工作。将设置注入所有子项目的一种方法是在testNoFail
中定义触发的AutoPlugin
。
project/*.scala
如果您想让sbt 然后做其他事情,那么一种自然的方法就是使用命令。这类似于人类向外壳中连续输入内容。
可以使用分号 override def requires = plugins.JvmPlugin
override def trigger = allRequirements
来编写命令。
;
之所以可行,是因为无论测试以前的状态如何,我们都可以安全地运行testQuick
task。
另请参见Sequencing How to系列,以了解其他对事物进行排序的方法。
运行:
override def buildSettings = {
addCommandAlias("testExtraShot", ";testNoFail;testQuick")
}
在sbt shell内。这将先运行> testExtraShot
,然后运行testNoFail
。
请注意,无论如何,我通过运行testQuick
绕过了Martin最初的“万一测试失败”的规范。可以实现这一点,但是要先进一些。
我们可以定义一个首先运行正常testQuick
的任务,然后根据返回的 result 值,更改 next 任务的继续。在sbt中,可以使用dynamic task来实现这种单子连续性。
我们通常试图避免这种组合,因为它阻止了任务引擎并行化并发任务,但是当我们需要if-then-do-something时它很方便。
以下实现了一个临时插件,该插件定义了一个动态任务:
test