在 SBT 中使用“sbt testOnly”从 jar 中运行测试?
Posted
技术标签:
【中文标题】在 SBT 中使用“sbt testOnly”从 jar 中运行测试?【英文标题】:Running tests from jar with "sbt testOnly" in SBT? 【发布时间】:2014-03-31 04:56:38 【问题描述】:作为 CI 设置的一部分,第一步是使用 SBT dist
创建一个包/jar。以下步骤是使用dist
-created jar 运行单元、集成和功能测试。
SBT 可以做到这一点吗?
通常我使用sbt testOnly "Unit.*"
,但这适用于项目的上下文。当已经有一个 jar 时,我找不到任何说明如何执行此操作的文档。
我正在使用 ScalaTest,我知道有一个跑步者可以使用 http://www.scalatest.org/user_guide/using_the_runner。但如果可能的话,使用 SBT 会更简单。
例如,我正在寻找这样的东西:
sbt testOnly "Unit.* -jar myjar.jar"
当我使用以下内容时,我的测试是否会包含在 jar 中:
sbt dist
?
编辑
-
我创建了一个新文件夹
我添加了build.sbt
,内容如下:
name := "abc"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.0"
我添加了lib
文件夹并将我的测试jar 复制到其中
我跑了sbt testOnly Unit.*
找不到任何测试
编辑 2
我尝试使用以下“正确”的 SBT 文件:
name := "ihs2tests"
version := "1.0-SNAPSHOT"
scalaVersion := "2.10.0"
unmanagedBase in Test := new java.io.File(".")
并将test.jar
移动到项目的根目录中。同样,没有找到任何测试。
【问题讨论】:
这应该可以帮助您入门:***.com/a/16409096/2197460. 测试代码通常不包含在dist
jar 中,但 @DaveSwartz 的链接可能对此有所帮助。
sbt test:dist
怎么样?这不包括(测试)dist jar 中的测试吗?
【参考方案1】:
通常我使用 sbt testOnly "Unit.*",但这适用于项目的上下文。当已经有一个 jar 时,我找不到任何说明如何执行此操作的文档。
SBT 中的test
-family 任务(以testOnly
为例)与通过sbt.inc.Analysis
实例返回已编译文件列表的compile
任务一起使用。我不知道如何修改它并将更改后的分析实例注入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 给定scalatest 标签,但我将使用 Specs2)。阅读测试框架的文档以了解如何执行此操作,对于 Specs2,它是 specs2.run
,如 Console output 中所述。
从测试 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.run
用于 Specs2,就好像该类是在命令行上执行的一样。 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 仍然存在。
【讨论】:
我将 build.sbt 和 tests.jar 复制到了一个新项目中,但它试图再次编译它,所以很遗憾这不起作用 再试一次!【参考方案2】:如果没有任何额外/手动设置,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 源代码和默认的 sbt
shell 脚本,该脚本在运行 sbt 启动器 jar 之前会进行大量设置。
【讨论】:
以上是关于在 SBT 中使用“sbt testOnly”从 jar 中运行测试?的主要内容,如果未能解决你的问题,请参考以下文章