为啥在使用“sbt it:test”时不执行 Play/Scala 项目中的集成测试?
Posted
技术标签:
【中文标题】为啥在使用“sbt it:test”时不执行 Play/Scala 项目中的集成测试?【英文标题】:Why are integration tests in a Play/Scala project not executed when using "sbt it:test"?为什么在使用“sbt it:test”时不执行 Play/Scala 项目中的集成测试? 【发布时间】:2014-11-07 05:08:32 【问题描述】:我有一个Play Framework 2.3 项目,我想将单元测试和功能测试分开如下:
-
运行
sbt test
应该运行单元测试并排除集成测试
运行 sbt it:test
应该只运行集成测试
Scala 文档建议使用project/Build.scala
,但我想使用build.sbt
和project/Build.scala
的组合,所以我的配置看起来像这样(我也尝试将所有配置放入Build.scala
):
build.sbt
....
libraryDependencies ++= Seq(
"com.typesafe.play" %% "play-json" % "2.2.3",
"org.scalatest" %% "scalatest" % "2.1.5" % "it, test",
"org.mockito" % "mockito-all" % "1.9.5" % "it, test"
)
def funTestFilter(name: String): Boolean = ((name endsWith "ItTest") || (name endsWith "IntegrationTest"))
def unitTestFilter(name: String): Boolean = ((name endsWith "Test") && !funTestFilter(name))
testOptions in IntegrationTest := Seq(Tests.Filter(funTestFilter))
testOptions in Test := Seq(Tests.Filter(unitTestFilter))
project/Build.scala
import sbt._
object Build extends Build
lazy val root =
Project("root", file("."))
.configs( IntegrationTest )
.settings( Defaults.itSettings : _* )
在此配置下运行 sbt test
确实排除了我的集成测试(以 IntegrationTest
结尾)但运行 sbt it:test
找不到任何测试。
文章建议将文件放在特定路径中,但我不知道 Play 项目的等效路径是什么。
使用标准源层次结构:
src/it/scala for Scala sources
src/it/java for Java sources
src/it/resources for resources that should go on the integration test classpath
【问题讨论】:
【参考方案1】:第一部分——关于在build.sbt
中设置集成测试——在另一个问题What would be the minimal setup of IntegrationTest configuration in sbt 0.13.x? 中进行了描述——它归结为build.sbt
中的以下条目:
Defaults.itSettings
lazy val root = project.in(file(".")).configs(IntegrationTest)
由于一个 Play 项目的定义如下:
lazy val root = (project in file(".")).enablePlugins(PlayScala)
你应该添加configs
,你就完成了。
lazy val root = project in file(".") enablePlugins(PlayScala) configs(IntegrationTest)
执行reload
或重新启动sbt/activator 会话并执行it:test
。
[it-play] $ it:test
[info] Updating file:/Users/jacek/sandbox/it-play/root...
[info] Resolving jline#jline;2.11 ...
[info] Done updating.
[success] Total time: 1 s, completed Sep 13, 2014 7:12:27 PM
关于集成测试在 Play 项目中的位置,简短的回答是在 shell 中执行show it:sourceDirectory
,即src/it
与scala
、java
和resources
目录下包含各自的来源。
在it
配置中添加测试框架库,即在build.sbt
中应该有类似的东西 - 注意it
配置:
"org.specs2" %% "specs2" % "2.4.2" % "it"
执行reload
sbt 会话或重新启动它,it:test
应该适用于 src/it/scala
下的所有测试的 Specs2 测试。
要缩小应执行的测试范围,请添加您的过滤器 - 确保它位于 Defaults.itSettings
行之后,因为顺序很重要,并且可以覆盖另一个:
val funTestFilter: String => Boolean = name =>
(name endsWith "ItTest") || (name endsWith "IntegrationTest")
testOptions in IntegrationTest += Tests.Filter(funTestFilter)
执行reload
或重启sbt 并执行it:test
。它应该工作。执行show it:testOptions
以确保您的设置正确加载:
[it-play] $ show it:testOptions
[info] List(Filter(<function1>))
为我工作的整个build.sbt
如下 - 它是由activator new it-play play-scala
创建的:
name := """it-play"""
version := "1.0-SNAPSHOT"
lazy val root = project in file(".") enablePlugins(PlayScala) configs(IntegrationTest)
scalaVersion := "2.11.1"
libraryDependencies ++= Seq(
jdbc,
anorm,
cache,
ws,
"org.specs2" %% "specs2" % "2.4.2" % "it"
)
Defaults.itSettings
val funTestFilter: String => Boolean = name =>
(name endsWith "ItTest") || (name endsWith "IntegrationTest")
testOptions in IntegrationTest += Tests.Filter(funTestFilter)
【讨论】:
谢谢!!!。我的项目不知道“PlayScala”是什么,这是我得到的错误:“/web/api-checkout/build.sbt:28: error: not found: value PlayScala”,但是,没有它似乎可以工作, 不知道不然会导致什么问题,暂时还没有发现问题。 使用 Play 2.3.9,我按照示例进行操作,但我的 IntegrationSpec.scala 无法编译,因为它找不到 PlaySpecification 即类 IntegrationSpec 扩展 PlaySpecification。知道为什么 SBT 没有在“它”阶段包含播放库吗?另外,我已将此添加到 build.sbt, "org.specs2" %% "specs2-core" % "3.5" % "it, test", "org.specs2" %% "specs2-junit" % "3.5" % "it, test", "org.specs2" %% "specs2-mock" % "3.5" % "it, test" 谢谢 好的,我在 "it" 中添加了 play-test,即 "com.typesafe.play" %% "play-test" % "2.3.9" % "it" 令人困惑的是,Play 的集成测试是“src/it”而不是“/it”,因为如果它在基本目录中的“/app”和“/test”旁边会更有意义,根据the Play Anatomy。我通过将build.sbt
中的设置更改为sourceDirectory in IntegrationTest := baseDirectory.value / "it"
,将我的集成测试移到了那里。然后它会找到通常的it/java
、it/scala
、it/resources
目录。
这是一个很奇怪的命名建议——在不区分大小写的情况下,UnitTest
也以ItTest
结尾,而事实上ItTest
解析为IntegrationTestTest
;-)【参考方案2】:
这就是我最终做的事情,这让我能够:
-
将我的集成测试保存在 play 的
/test
目录中
运行sbt test
进行单元测试,运行sbt fun:test
进行功能/集成测试
这里是build.sbt
,不需要project/Build.scala
libraryDependencies ++= Seq( ... "com.typesafe.play" %% "play-json" % "2.2.3", "org.scalatest" %% "scalatest" % "2.1.5" % "test", "org.mockito" % "mockito-all" % "1.9.5" % "test" ) lazy val FunTest = config("fun") extend(Test) def funTestFilter(name: String): Boolean = ((name endsWith "ItTest") || (name endsWith "IntegrationTest")) def unitTestFilter(name: String): Boolean = ((name endsWith "Test") && !funTestFilter(name)) lazy val root = project in file(".") configs(FunTest) settings( inConfig(FunTest)(Defaults.testTasks) : _*) testOptions in FunTest := Seq(Tests.Filter(funTestFilter)) testOptions in Test := Seq(Tests.Filter(unitTestFilter))
【讨论】:
我真的很喜欢这个解决方案,因为我可以克隆并进入任何选择的 IDE。如果我创建一个新的测试文件夹,那么从今天开始,我必须将 IDE 特定的东西放入我的构建(ick)中,或者有一个额外的 IDE 步骤来告诉 IDE 我的新文件夹(也不是很好)。以上是关于为啥在使用“sbt it:test”时不执行 Play/Scala 项目中的集成测试?的主要内容,如果未能解决你的问题,请参考以下文章