【发布时间】:2020-09-21 04:00:14
【问题描述】:
我有一个 SBT 项目,其中多个子项目聚合在一个根项目中。我想确保测试套件是按顺序运行的,所以我设置了Global / concurrentRestrictions += Tags.limit(Tags.Test, 1)。
不过,我还使用Tests.Setup()/Cleanup() 来为每个子项目的测试套件初始化大量内存资源。我面临的问题是concurrentRestrictions 对测试设置和清理没有影响:当我希望它在每个测试套件之前和之后按顺序运行时,我的所有测试设置和清理逻辑都是并行运行的。
这是一个示例build.sbt:
import sbt._
import scala.sys.process._
lazy val testSettings = Seq(
testOptions ++= Seq(
Tests.Setup(() => {
println(s"setup for ${name.value}")
}),
Tests.Cleanup(() => {
println(s"cleanup for ${name.value}")
})
)
)
Global / libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "3.1.0" % "test"
)
def module(path: String) = {
Project(path, file(path))
.settings(testSettings)
}
lazy val module1 = module("module1")
lazy val module2 = module("module2")
lazy val module3 = module("module3")
lazy val root = (project in file("."))
.aggregate(module1, module2, module3)
Global / concurrentRestrictions += Tags.limit(Tags.Test, 1)
以及我为每个子项目使用的虚拟测试:
import org.scalatest.matchers.should.Matchers
import org.scalatest._
class DummyTest extends FlatSpec with Matchers {
"this test" should "run a test for module 1" in {}
}
运行sbt test 给出以下输出,以并发的变幻莫测为模:
$ sbt test
[info] Loading settings for project global-plugins from plugins.sbt ...
[info] Loading global plugins from /home/jejost/.sbt/1.0/plugins
[info] Loading project definition from /home/jejost/dev/tmp/sbt-yunowork/project
[info] Loading settings for project root from build.sbt ...
[...]
setup for module1
setup for module3
setup for module2
[info] DummyTest:
[info] this test
[info] - should run a test for module 1
[info] DummyTest:
[info] this test
[info] - should run a test for module 3
[info] DummyTest:
[info] this test
[info] - should run a test for module 2
cleanup for module1
cleanup for module3
cleanup for module2
[...]
当我想要的行为是这样的:
$ sbt test
[info] Loading settings for project global-plugins from plugins.sbt ...
[info] Loading global plugins from /home/jejost/.sbt/1.0/plugins
[info] Loading project definition from /home/jejost/dev/tmp/sbt-yunowork/project
[info] Loading settings for project root from build.sbt ...
[...]
setup for module1
[info] DummyTest:
[info] this test
[info] - should run a test for module 1
cleanup for module1
setup for module3
[info] DummyTest:
[info] this test
[info] - should run a test for module 3
cleanup for module3
setup for module2
[info] DummyTest:
[info] this test
[info] - should run a test for module 2
cleanup for module2
[...]
(模块 1、模块 3、模块 2 的顺序对我来说并不重要,只要设置/拆卸在每个子项目之前/之后是顺序的)
是否可以像这样确保顺序测试设置和清理,理想情况下无需定义我自己的自定义任务?
我正在使用 SBT 1.3.4。
编辑:这已被标记为以下问题的重复:How to run subprojects tests (including setup methods) sequentially when testing 这确实是同一个问题,但是,接受的答案不起作用,并且不会改变任务运行顺序!我试图重现另一个问题的设置,看看它是否是 SBT 中的回归,不幸的是,OP 的 SBT 版本太旧,无法在我的机器上成功构建。
【问题讨论】:
-
不,不是:我不知道这是否是由于 SBT 中的行为变化/回归,但因为测试设置/清理在其自己的单独任务中运行,添加
parallelExecution in Global := false可确保只有一个子项目的测试设置任务同时运行,但它不会阻止其他子项目设置任务在该项目的测试和清理完成之前运行。 -
在实践中,我没有看到与
parallelExecution in Global := false并行运行的任务,但执行顺序没有变化,添加parallelExecution in ThisBuild := false时也没有任何变化 -
恐怕你无法实现这一点,正如Forking tests 中所阐述的那样:
Setup和Cleanup在一个组被分叉时,实际的测试类加载器无法提供动作。 我知道你没有使用组,但如果你不能用组来做,你可能根本做不到。
标签: scala testing concurrency sbt