sbt testQuick遇传递依赖代码变更时不重新运行的问题
问题:修改bar模块代码后testQuick未触发测试运行
我用testQuick做TDD测试时碰到个问题,已简化成最小复现示例,怀疑是配置问题,求排查:
有三个Scala项目:tests、foo、bar,依赖关系是tests → foo → bar。修改foo的代码时,源码会重新编译,测试也会自动重新运行;但修改bar的代码(比如把返回值改成false),只有bar的源码会重新编译,测试完全没跑,输出如下:
[info] 1. Monitoring source files for testquick/tests/Test/testQuick... [info] Press <enter> to interrupt or '?' for more options. [info] Build triggered by <shortened>/bar/src/main/scala/Bar.scala. Running 'tests/Test/testQuick'. [info] compiling 1 Scala source to <shortened>/bar/target/scala-3.2.2/classes ... [info] Passed: Total 0, Failed 0, Errors 0, Passed 0 [info] No tests to run for tests / Test / testQuick [success] Total time: 1 s, completed May 19, 2023, 11:18:15 PM [info] 2. Monitoring source files for testquick/tests/Test/testQuick... [info] Press <enter> to interrupt or '?' for more options.
测试环境:sbt 1.8.3,执行命令:sbt "~tests/Test/testQuick"
项目配置与代码
build.sbt
ThisBuild / version := "0.1.0-SNAPSHOT" ThisBuild / scalaVersion := "3.2.2" lazy val tests = project.dependsOn(foo).settings( libraryDependencies += "org.scalactic" %% "scalactic" % "3.2.16", libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.16" % "test" ) lazy val foo = project.dependsOn(bar) lazy val bar = project
tests/src/test/scala/TestSpec.scala
import org.scalatest.* import flatspec.* class TestSpec extends AnyFlatSpec { "Foo" should "be true" in { assert(Foo.doFoo()) } }
foo/src/main/scala/Foo.scala
object Foo { def doFoo(): Boolean = Bar.doBar() }
bar/src/main/scala/Bar.scala
object Bar { def doBar(): Boolean = true }
解决方案
这是因为sbt的testQuick默认只会检测直接依赖的变更。tests模块直接依赖foo,所以foo变更会触发tests的测试;但bar是tests的间接依赖,默认不会被testQuick的监听逻辑识别。
有两种靠谱的解决方法:
- 让tests直接依赖bar(语义上可能冗余,但能快速解决触发问题)
修改build.sbt中tests项目的配置:
lazy val tests = project.dependsOn(foo, bar).settings( libraryDependencies += "org.scalactic" %% "scalactic" % "3.2.16", libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.16" % "test" )
- 配置
watchTriggeredBy监听间接依赖变更
在tests项目的settings里添加监听规则,让tests的测试任务感知bar的编译变更:
lazy val tests = project.dependsOn(foo).settings( libraryDependencies += "org.scalactic" %% "scalactic" % "3.2.16", libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.16" % "test", // 添加这行配置 Test / watchTriggeredBy += bar / Compile / compile )
如果暂时不想调整配置,也可以用~tests/Test/test代替testQuick,但test会运行所有测试,而testQuick只跑受影响的测试,所以更推荐前两种方法。
内容的提问来源于stack exchange,提问作者Tanju Erinmez
相关产品推荐
相关产品推荐

