如何在 sbt 中的测试任务之前附加自定义任务以执行?

Posted

技术标签:

【中文标题】如何在 sbt 中的测试任务之前附加自定义任务以执行?【英文标题】:How to attach custom task to execute before the test task in sbt? 【发布时间】:2012-01-23 05:01:07 【问题描述】:

我正在将 SBT 与 Play 框架一起使用。

我创建了一个自定义 TaskKey 来在我的项目中运行 javascript 测试:

import sbt._
import sbt.Process._
import PlayProject._

object ApplicationBuild extends Build 

  val testJsTask = TaskKey[Unit]("testJs", "Run javascript tests.") := 

  val main = PlayProject("xxx", 1.0, Seq())
    .settings(defaultScalaSettings: _*)
    .settings(testJsTask)

到目前为止一切顺利。

我想在有人执行test 任务时始终运行此testJsTask

我猜应该是这样的:

test in Test <<= (test in Test).dependsOn(testJsTask)

我不知道应该如何准确定义它。如何将依赖项添加到现有任务,如“测试”或“构建”?

更新

@Christian 提出更改后,构建定义如下所示:

object ApplicationBuild extends Build 
  val testJsTask = TaskKey[Unit]("testJs", "Run tests for javascript client.")
  def testJs = 

  val main = PlayProject("xxx", 1.0, Seq())
    .settings(defaultScalaSettings: _*)
    .settings(testJsTask := testJs)

  (test in Test) <<= (test in Test) dependsOn (testJs)

不幸的是,该解决方案也不起作用:

[error] /xxx/project/Build.scala:21: not found: value test
[error]   (test in Test) <<= (test in Test) dependsOn (testJs)
[error]    ^
[error] one error found
[error] file:/xxx/project/default-f468ae/compile:compile: Compilation failed

【问题讨论】:

你成功了吗?我最近的编辑对您有帮助吗? 不幸的是,我没有办法在 Play 版本上做同样的事情:/ 我会尝试做更多的测试,如果有任何成功,我会在这里报告。 我很想看看你是否找到了解决办法。 只为未来的读者:(test in Test) := (test in Test).dependsOn(otherTask).value 为我工作 【参考方案1】:

这是一种方法:

定义任务键:

val testJsTask = TaskKey[Unit]("testJs", "Run javascript tests.")    

在您的项目设置中定义任务:

testJsTask <<= testJs

使测试依赖于它:

(test in Test) <<= (test in Test) dependsOn (testJs)

testJs 可以定义如下:

  def testJs = (streams) map  (s) => 
    s.log.info("Executing task testJs")
    // Your implementation
  

[编辑] 您必须在项目设置中定义任务依赖项。为了 一个“正常”的项目,你可以这样做:

  lazy val testProject = Project(
    "testProject",
    file("testProject"),
    settings = defaultSettings ++ Seq(
      testJsTask <<= testJs,
      (test in Test) <<= (test in Test) dependsOn (testJsTask)
    )
  )

【讨论】:

不知何故这对我来说看起来不完整。我想要做的是确保当有人运行“测试”命令时,除了所有其他测试之外,它还将执行 testJs。另外我看到你根本没有使用':='符号,我知道在构建任务时需要它 - 还是我错了?编辑:我看到了您的编辑,现在它开始变得更有意义了,我会立即尝试;) 你可以直接用:=定义一个任务。我更喜欢另一种可能性,因为这样我可以将任务键与实际任务分开。 我还是和以前一样的问题:Build.scala:19: not found: value test。 [错误](测试中的测试) 您能发布您当前的构建脚本吗? 我没用过play框架,但可能一个PlayProject没有(Test in Test)?【参考方案2】:

Play 2.2.x 使用 SBT 0.13(请参阅What’s new in Play 2.2)。这带来了一些在 build.sbt 本身中编写任务的新方法(无需借助 project/ 子目录中的 Scala 文件)。

如果您碰巧使用 Play 2.2.x,您可以在 build.sbt 中定义任务之间的依赖关系,如下所示:

lazy val testJsTask = taskKey[Unit]("Run JavaScript tests.")

testJsTask := 
  println("Running JavaScript tests...")
  java.util.concurrent.TimeUnit.SECONDS.sleep(3)
  println("...done.")


test in Test := 
  testJsTask.value
  (test in Test).value

更多详情请参阅 SBT 官方文档中的Tasks。

【讨论】:

这是顺序运行任务还是同时运行? 依次。首先是 testJsTask,然后是测试任务。 据我了解这是不正确的@htomek scala-sbt.org/release/docs/… 使用Def.sequential() 按顺序运行任务scala-sbt.org/release/docs/Howto-Sequencing.html【参考方案3】:

对我来说,使用 dependsOn 语法不起作用。相反,我使用了测试的setup functionality 或sbt

您的示例将类似于以下内容:

val testJsTask = TaskKey[Unit]("testJs", "Run javascript tests.")

testJsTask := 
  // ...whatever logic


// then inside your project settings
Test / testOptions += Tests.Setup(() => testJsTask.value)

请注意末尾的.value。如果没有它,将是在不调用它的情况下引用函数。

【讨论】:

以上是关于如何在 sbt 中的测试任务之前附加自定义任务以执行?的主要内容,如果未能解决你的问题,请参考以下文章

你如何在 sbt 中编写任务?

SBT插件——编译前执行自定义任务

在SBT构建中的多项目构建中的自定义任务

SBT:如何在多个任务中重用带有参数的代码?

无法从 AutoPlugin 的命令运行自定义 sbt 任务

从sbt任务中的stdin读取