[英]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.