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

时间:2016-07-08 16:23:59

标签: scala sbt scalatest sbt-assembly

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

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

我的解决方案现在有效,但它有严重的缺点。我只是使用Fork.javaorg.scalatest.tools.Runner运行器上调用Java,其类路径设置为包含测试代码和胖jar以及所有测试依赖项。缺点是没有SBT测试丰富度有效,没有testQuick,没有testOnly,测试失败报告在stdout上。

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

2 个答案:

答案 0 :(得分:1)

这就是我的目标(对于 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

答案 1 :(得分:0)

尝试像这样将胖子罐添加到测试类路径的第一个位置

#include <stdio.h>
#include "my_files.h"

int main(void)
{
    printf("cpu_list[0] is %d\n", cpu_list[0]);
    printf("cpu_list[1] is %d\n", cpu_list[1]);

    not_main();

    printf("cpu_list[0] is %d\n", cpu_list[0]);
    printf("cpu_list[1] is %d\n", cpu_list[1]);

    return 0;
}

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

我们可以像这样在自定义命令Public void onNumberButtonClick(actionevent e) { Button b = (button) e. Getsource() ; AppentText(b.gettext()); } 中捕获这个想法

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

testAgainstFatJar检查胖子罐确实在第一位置