繁体   English   中英

如何使用 SBT 对胖罐运行 ScalaTest 测试?

[英]How to use SBT to run ScalaTest tests against a fat jar?

我有一个简单的 SBT 项目,由src/main/scala的一些 Scala 代码和src/test/scala一些测试代码组成。 我使用sbt-assembly插件来创建一个用于部署到远程系统的胖 jar。 胖 jar 包含 Scala 项目的所有依赖项,包括 Scala 运行时本身。 这一切都很好。

现在我正试图找出一种方法,我可以针对胖罐运行 Scala 测试。 我尝试了显而易见的事情,创建一个扩展Test配置的新配置并将dependencyClasspath路径修改为胖 JAR 而不是默认值,但是这失败了,因为(我假设是因为)Scala 运行时包含在胖 jar 中并以某种方式发生冲突使用已经加载的 Scala 运行时。

我的解决方案现在有效,但它有严重的缺点。 我只是用Fork.java调用Java的org.scalatest.tools.Runner亚军与类路径设置为包含测试代码和脂肪的罐子和所有的测试依赖。 缺点是 SBT 测试丰富性都testQuick ,没有testQuick ,没有testOnly ,并且测试失败报告在标准输出上。

我的问题归结为:当这些测试不依赖于相应的 SBT compile输出,而是依赖于本身包含所有 Scala 运行时的胖 JAR 文件时,如何使用 SBT 的测试命令来运行测试?

这就是我的目标(对于 specs2,但可以调整)。 这基本上就是你所说的 Fork 解决方案,但我想我会把它留在这里,以防有人想知道那可能是什么。 不幸的是,我认为您不能作为 SBT 测试运行器“正式”运行它。 我还应该补充一点,即使这是 Scala,您仍然需要 Fork.java,因为 Fork.scala 依赖于我似乎没有的 runner 类。

test.sbt(或 build.sbt,如果你想在那里放一堆东西——如果你想组织,SBT 会读取根目录中的所有 .sbt 文件):

// Set up configuration for building a test assembly
Test / assembly / assemblyJarName := s"${name.value}-test-${version.value}.jar"
Test / assembly / assemblyMergeStrategy := (assembly / assemblyMergeStrategy).value
Test / assembly / assemblyOption := (assembly / assemblyOption).value
Test / assembly / assemblyShadeRules := (assembly / assemblyShadeRules).value
Test / assembly / mainClass := Some("org.specs2.runner.files")
Test / test := {
  (Test / assembly).value

  val assembledFile: String = (Test / assembly / assemblyOutputPath).value.getAbsolutePath
  val minimalClasspath: Seq[String] = (Test / assembly / fullClasspath).value
    .filter(_.metadata.get(moduleID.key).get.organization.matches("^(org\\.(scala-lang|slf4j)|log4j).*"))
    .map(_.data.getAbsolutePath)

  val runClass: String = (Test / assembly / mainClass).value.get
  val classPath: Seq[String] = Seq(assembledFile) ++ minimalClasspath
  val args: Seq[String] = Seq("-cp", classPath.mkString(":"), runClass)

  val exitCode = Fork.java((Test / assembly / forkOptions).value, args)

  if (exitCode != 0) {
    throw new TestsFailedException()
  }
}
Test / assembly / test := {}

build.sbt 的变化:

lazy val root = (project in file("."))
  .settings(/* your original settings are here */)
  .settings(inConfig(Test)(baseAssemblySettings): _*) // enable assembling in test

尝试将胖子罐添加到测试类路径的第一个位置,如下所示

Test / fullClasspath := Attributed.blank((assembly / assemblyOutputPath).value) :: (Test / fullClasspath).value.toList

在这里, assemblyOutputPath给出了胖子罐子的路径。 我的理解是JVM将在路径上遇到的第一个类加载,因此实际上我们将测试胖子罐。

我们可以像这样在自定义命令testAgainstFatJar捕获这个想法

commands += Command.command("testAgainstFatJar") { state =>
    "set assembly / test := {}" ::
    "assembly" ::
    "set Test / fullClasspath := Attributed.blank((assembly / assemblyOutputPath).value) :: (Test / fullClasspath).value.toList" ::
    "test" :: state
}

使用show Test / fullClasspath检查胖罐是否确实在第一个位置

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM