sbt test

概要

sbt [query / ] test [testname1 testname2] [ -- options ]

描述

test 任务提供编译和运行测试的方式。

默认情况下,sbt 2.x 中的 test 任务:

  1. 子项目并行。并行编译由 query 指定的相关子项目。
  2. 测试套件并行。将发现的测试套件映射为任务并并行执行。
  3. 增量测试。仅运行上次失败、从未运行,或 sbt 检测到测试或其依赖有变更的测试。
  4. 缓存。测试结果在机器范围内缓存,并可选择远程缓存。

测试的标准源位置为:

  • src/test/scala/ 中的 Scala 源
  • src/test/java/ 中的 Java 源
  • src/test/resources/ 中用于测试 classpath 的资源

测试中可通过 java.lang.Classjava.lang.ClassLoadergetResource 方法访问资源。

测试接口

sbt 为基于 JVM 的测试框架定义了通用接口,支持自动发现测试套件和并行执行。默认情况下 sbt 与 MUnitScalaTestHedgehogScalaCheckSpecs2WeaverZIO TestJUnit 4 集成;这意味着您只需将测试框架添加到 classpath 即可与 sbt 配合使用。例如,可通过将其声明为 libraryDependency 使用 MUnit:

lazy val munit = "org.scalameta" %% "munit" % "1.2.0"

libraryDependencies += munit % Test

上述中,Test 表示 Test 配置,意味着 MUnit 仅出现在测试 classpath 中,主源不需要它。

JUnit

JUnit 5 支持由 sbt-jupiter-interface 提供。要为项目添加 JUnit Jupiter 支持,请在项目主 build.sbt 文件中添加 jupiter-interface 依赖。

libraryDependencies += "com.github.sbt.junit" % "jupiter-interface" % "0.15.1" % Test

并将 sbt-jupiter-interface 插件添加到 project/plugins.sbt

addSbtPlugin("com.github.sbt.junit" % "sbt-jupiter-interface" % "0.15.1")

JUnit 4 支持由 junit-interface 提供。请在项目主 build.sbt 文件中添加 junit-interface 依赖。

libraryDependencies += "com.github.sbt" % "junit-interface" % "0.13.3" % Test

测试过滤

在 sbt 2.x 中,test 任务接受以空格分隔的测试名称列表。例如:

> test example.ExampleSuite example.ExampleSuite2

示例输出:

> test example.ExampleSuite example.ExampleSuite2
[info] compiling 1 Scala source to /tmp/foo/target/out/jvm/scala-3.7.2/foo/backend ...
[info] compiling 2 Scala sources to /tmp/foo/target/out/jvm/scala-3.7.2/foo/test-backend ...
example.ExampleSuite:
  + addition 0.003s
example.ExampleSuite2:
  + subtraction 0.003s
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] elapsed time: 3 s, cache 49%, 25 disk cache hits, 26 onsite tasks

也支持通配符:

> test *Example*

增量测试

除显式过滤外,test 任务仅运行满足以下条件之一的测试:

  • 上次运行失败的测试
  • 之前未运行过的测试
  • 有一个或多个传递依赖(可能在不同项目中)被重新编译的测试。

完整测试

要运行未缓存的完整测试(如 sbt 1.x),请使用 testFull 任务。

其他任务

主源可用的任务通常也可用于测试源,但在命令行中需加 Test / 前缀,在 Scala 代码中也以 Test / 引用。这些任务包括:

  • Test / compile
  • Test / console
  • Test / consoleQuick
  • Test / run
  • Test / runMain

详见 sbt run 了解这些任务。

输出

默认情况下,每个测试源文件的日志会缓冲到该文件所有测试完成。可通过设置 logBuffered 禁用:

Test / logBuffered := false

测试报告

默认情况下,sbt 会为构建中所有测试生成 JUnit XML 测试报告,位于项目的 target/test-reports 目录。可通过禁用 JUnitXmlReportPlugin 来禁用此功能。

val myProject = (project in file(".")).disablePlugins(plugins.JUnitXmlReportPlugin)

选项

测试框架参数

测试框架参数可在命令行中通过 -- 分隔符传递给 test 任务。例如:

> test org.example.MyTest -- -verbosity 1

要在构建中指定测试框架参数,添加由 Tests.Argument 构造的选项:

Test / testOptions += Tests.Argument("-verbosity", "1")

要仅为特定测试框架指定:

Test / testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-verbosity", "1")

设置与清理

使用 Tests.SetupTests.Cleanup 指定设置和清理操作。它们接受 () => Unit 类型或 ClassLoader => Unit 类型的函数。接受 ClassLoader 的变体会接收用于运行测试的(或曾用于运行测试的)类加载器,可访问测试类和测试框架类。

Note

fork 时无法提供包含测试类的 ClassLoader,因其在另一个 JVM 中。 此情况下仅使用 () => Unit 变体。

示例:

Test / testOptions += Tests.Setup( () => println("Setup") )
Test / testOptions += Tests.Cleanup( () => println("Cleanup") )
Test / testOptions += Tests.Setup( loader => ... )
Test / testOptions += Tests.Cleanup( loader => ... )

禁用测试套件并行执行

默认情况下,sbt 在与自身相同的 JVM 中并行运行所有任务。由于每个测试套件映射为一个任务,测试默认也并行运行。要使给定项目内的测试串行执行:

Test / parallelExecution := false

注意,不同项目的测试仍可能并发执行。

过滤类

若您只想运行名称以 "Test" 结尾的测试类,使用 Tests.Filter

Test / testOptions := Seq(Tests.Filter(s => s.endsWith("Test")))

Fork 测试

该设置:

Test / fork := true

指定所有测试将在单个外部 JVM 中执行。

可通过 testGrouping 键更精细控制测试如何分配到 JVM 以及传递哪些选项。

通过设置 Tags.ForkedTestGroup 标签的限制可控制同时运行的 fork JVM 数量,默认为 1。当组被 fork 时,无法为 SetupCleanup 操作提供实际测试类加载器。