scala - sbt:如何编写仅在测试失败时才运行 testQuick 的任务?

标签 scala sbt

这个问题来自 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)所有子项目的一种方法是定义触发的 AutoPluginproject/*.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/

    相关文章:

    scala - 依赖于路径的类型 - 以下代码有什么问题?

    在大型数据集上将 Spark DataFrame 从长到宽 reshape

    java - 使用 SBT 从另一个 jar 读取 ManifestAttributes

    java - Sbt 在尝试运行它时在通用包装器错误中没有给出匹配的架构

    json - 使用 Play! 将两个 json 对象渲染到 View 中斯卡拉2.3

    scala - Scala 中的 Joda 编码/解码

    json - Spark from_json - StructType 和 ArrayType

    powershell - 在Windows PowerShell中杀死SBT

    playframework - 如何为 sbt 测试指定带有 sbt 0.12.2 的配置文件?

    scala - Typesafe Play WS 作为 SBT 项目中的依赖项