SBT:如何修改它:使用调用原始测试任务的任务进行测试?

时间:2013-11-23 00:28:13

标签: scala sbt

在下面的Build.scala文件的片段中,itTestWithService任务在运行集成测试之前和之后启动测试服务器。

我想将此itTestWithService任务附加到它:test键。但是如何?

  lazy val mohs =
    Project(id = "mohs", base = file("."))
     .settings (
        // I'd like the following but it creates a cycle that fails at runtime:
        // test in IntegrationTest <<= testWithService   
        itTestWithService <<= testWithService
      )

  val itTestWithService = taskKey[Unit]("run integration test with background server")

  /** run integration tests against a test server.  (the server is started before the tests and stopped after the tests) */
  lazy val testWithService = Def.task {
    val log = streams.value.log
    val launched = (start in testService).value
    launched match {
      case Success(_) =>
        testAndStop.value
      case Failure(e) =>
        val stack = e.getStackTrace().mkString("\n")
        log.error(s"failed to start test server: $e \n ${stack}")
    }
  }

  /** run integration tests and then stop the test server */
  lazy val testAndStop = Def.taskDyn {
    val _ = (test in IntegrationTest).value
    stop in testService
  }

2 个答案:

答案 0 :(得分:2)

在一个相关的github issue discussion中,Josh提出了一种解决我所询问的特定案例的方法(覆盖它:使用调用原始测试任务的任务进行测试)。

该方法通过重新实现测试任务来工作。我不知道是否有更通用的方式来访问任务的原始版本。 (更通用的方式是比这个更好的答案!)

以下是如何重新实现它:测试任务:

  /** run integration tests (just like it:test does, but explicitly so we can overwrite the it:test key */
  lazy val itTestTask: Initialize[Task[Unit]] = Def.taskDyn {
    for {
      results <- (executeTests in IntegrationTest)
    } yield { Tests.showResults(streams.value.log, results, "test missing?") }
  }

这是复合集成测试任务(从原始问题中略微演变,尽管该版本也应该起作用):

  /** run integration tests against a test server.  (the server is started before the tests and stopped after the tests) */
  lazy val testWithServiceTask = Def.taskDyn {
    (start in testService).value match {
      case Success(_) =>
        testAndStop
      case Failure(e) =>
        val stack = e.getStackTrace().mkString("\n")
        streams.value.log.error(s"failed to start test server: $e \n ${stack}")
        emptyTask
    }
  }

  /** run integration tests and then stop the test server */
  lazy val testAndStop = Def.taskDyn {
    SbtUtil.sequence(itTestTask, stop in testService)
  }

  val emptyTask = Def.task {}

现在将我们构建的复合任务插入其中:测试键不会创建一个循环:

  lazy val mohs =
    Project(id = "mohs", base = file("."))
      .settings (
        test in IntegrationTest <<= testWithServiceTask,
      )

答案 1 :(得分:1)

您可以在build.scala中添加自定义测试代码。这是我的一个项目的示例代码。请记住,您不必将其绑定到它:test。你可以任意命名。

lazy val AcceptanceTest = config("acc") extend(Test)

  lazy val Kernel = Project(
    id = "kernel",
    base = file("."),
    settings = defaultSettings ++ AkkaKernelPlugin.distSettings ++ Seq(
        libraryDependencies ++= Dependencies.Kernel,
        distJvmOptions in Dist := "-Xms256M -Xmx2048M",
        outputDirectory in Dist := file("target/dist"),
        distMainClass in Dist := "akka.kernel.Main system.SystemKernel"
      )
  ).configs(AcceptanceTest)
   .settings(inConfig(AcceptanceTest)(Defaults.testTasks): _*)
   .settings(testOptions in AcceptanceTest := Seq(Tests.Argument("-n",
     "AcceptanceTest"), Tests.Argument("-oD")))

请注意顶部的懒惰部分和.configs部分。

使用该设置,当我输入acc:test时,它会使用AcceptanceTestTag运行所有测试。您可以将服务器作为测试套件调用的一部分来启动。甚至可以通过需要服务器标记测试而不需要它,这样一旦你的套件变大并且运行时间更长,你就可以将它们分开。

编辑:已添加以回复评论。

要标记测试,请创建一个这样的标记

import org.scalatest.Tag
object AcceptanceTest extends Tag("AcceptanceTest")

然后把它放在你的测试中......

it("should allow any actor to subscribe to any channel", AcceptanceTest) {

这与上面相同的构建设置相同。当我调用acc:test。

时,只会运行带有That标签的测试

您的问题让我想到的是我在同样情况下使用的解决方案。现在,你正在build.scala做的工作。我不确定你是否有可能在那里做你所说的......但我所做的却是同样的事情,但有点不同。我有一个特点,我混入所有需要流浪服务器的测试。我将使用它的测试标记为VagrantTest。

它就像一个单身人士。如果一个或多个测试需要它,它会启动。但它只能启动一个,所有测试都使用它。

你可以尝试做同样的事情,但要覆盖它:在配置文件中测试。而不是上面例子中的“acc”,而是“把它”。如果那不是你想要的,可能要看看是否还有其他人。

所以,基本上当我调用它时:测试它访问运行所有使用IntegrationTest测试标记的测试(以及那些使用VagrantTest和其他一些测试标记)。因此,所有运行时间较长的服务器测试都不会运行太多(耗时太长)。