在SBT中使用“sbt testOnly”从jar运行测试?

时间:2014-02-27 16:09:14

标签: scala sbt scalatest

作为CI设置的一部分,第一步是使用SBT dist创建包/ jar。以下步骤是使用dist创建的jar运行单元,集成和功能测试。

用SBT可以做到吗?

通常我使用sbt testOnly "Unit.*",但这可以在项目的上下文中使用。我找不到任何文档显示如何在已经有罐子的情况下执行此操作。

我正在使用ScalaTest,我知道有一个跑步者,我可以使用http://www.scalatest.org/user_guide/using_the_runner。但如果可能的话,使用SBT会更简单。

举个例子,我正在寻找这样的东西:

sbt testOnly "Unit.* -jar myjar.jar"

当我使用以下内容时,我的测试是否会包含在jar中:

sbt dist

修改

  1. 我创建了一个新文件夹
  2. 我添加了build.sbt以下内容:

    name := "abc"
    
    version := "1.0-SNAPSHOT"
    
    scalaVersion := "2.10.0"
    
  3. 我添加了lib文件夹并将我的测试jar复制到其中

  4. 我跑了sbt testOnly Unit.*

  5. 找不到任何测试

  6. 编辑2

    我尝试使用以下“正确”的SBT文件:

    name := "ihs2tests"
    
    version := "1.0-SNAPSHOT"
    
    scalaVersion := "2.10.0"
    
    unmanagedBase in Test := new java.io.File(".")
    

    并将test.jar移到项目的根目录中。再次,没有发现任何测试。

2 个答案:

答案 0 :(得分:1)

  

通常我使用sbt testOnly“Unit。*”,但这适用于项目的上下文。我找不到任何文档显示如何在已经有罐子的情况下执行此操作。

SBT中的test - 族任务(以testOnly为例)与compile任务一起使用,该任务通过sbt.inc.Analysis实例返回已编译文件的列表。我无法弄清楚如何修改它并将已更改的Analysis实例注入testOnly,因此它知道我将要运行的测试存在。

我正在提出另一种解决方案 - 一招

将测试类打包到具有test:package任务的jar,如下所示:

[test-lib]> test:package
[info] Updating {file:/Users/jacek/sandbox/so/test-lib/}test-lib...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Compiling 1 Scala source to /Users/jacek/sandbox/so/test-lib/target/scala-2.10/test-classes...
[info] Packaging /Users/jacek/sandbox/so/test-lib/target/scala-2.10/test-lib_2.10-0.1-SNAPSHOT-tests.jar ...
[info] Done packaging.
[success] Total time: 9 s, completed Mar 4, 2014 11:34:13 PM

当您拥有测试jar时,您可以在命令行上执行测试框架而不使用 SBT(我假设您在给定标记的情况下使用ScalaTest,但我将使用Specs2 )。阅读测试框架的文档,了解如何执行此操作,并按照Console output中的描述阅读specs2.run的Specs2。

从测试jar执行测试需要定义一个适当的CLASSPATH,可能很容易也可能不容易。这就是SBT可以提供很大帮助的地方 - 管理依赖关系,从而管理CLASSPATH。

创建另一个SBT项目并将测试jar保存在lib子目录中以使其位于CLASSPATH上(如Unmanaged dependencies中所述)。

  

lib中的依赖关系遍历所有类路径(用于编译,测试,运行和控制台)。

添加样本build.sbt,将测试框架定义为项目的依赖项。对于Specs2,它如下(我使用了the Specs2 home page中描述的默认配置):

libraryDependencies += "org.specs2" %% "specs2" % "2.3.8" % "test"

scalacOptions in Test ++= Seq("-Yrangepos")

技巧是执行测试框架的主类,例如对于Specs2,specs2.run,就好像该类是在命令行上执行的一样。 SBT帮助test:runMain

[my-another-project]> test:runMain specs2.run HelloWorldSpec
[info] Running specs2.run HelloWorldSpec
HelloWorldSpec

The 'Hello world' string should
+ contain 11 characters
+ start with 'Hello'
+ end with 'world'

Total for specification HelloWorldSpec
Finished in 62 ms
3 examples, 0 failure, 0 error

Exception: sbt.TrapExitSecurityException thrown from the UncaughtExceptionHandler in thread "run-main-0"
[success] Total time: 5 s, completed Mar 4, 2014 11:15:14 PM

不要担心这个Exception,因为它来自SBT,从Specs2中捕获exit(在测试执行后),因此SBT保持运行。

答案 1 :(得分:0)

似乎SBT无法在没有任何额外/手动设置的情况下读取jar文件 - 我可能错了,但我没有在文档中找到任何内容。所以我尝试了这样的事情来简化任务:

unzip some-test.jar

java -jar sbt-launch.jar \
  'set scalaSource in Test := new java.io.File(".")' \
  'set fullClasspath in Test += Attributed.blank(file("."))' \
  'test'

这样运行没有错误,但找不到测试。

如果我添加'set includeFilter in (Test, unmanagedSources) := "*Suite*.class"'以强制它查找测试,它显然会失败,因为它需要*.scala个文件,而不是编译的*.class文件。

我不是SBT专家,但我认为这必须接近解决方案。必须有一种方法以编程方式从jar路径读取所有文件,然后告诉测试框架使用*.class文件。

此时使用Scalatest测试运行器或使用该项目从sbt运行测试似乎更合理。

如果您想深入挖掘,请查看SBT源代码和默认{​​{1}} shell脚本,该脚本在运行sbt启动程序jar之前进行大量设置。