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