为什么使用"sbt it:test"时,在Play/Scala项目中集成测试没有被执行?

14

我有一个Play框架 2.3项目,希望按照以下方式分离单元测试和功能测试:

  1. 运行sbt test应该只运行单元测试并排除集成测试
  2. 运行sbt it:test应该只运行集成测试

Scala文档建议使用project/Build.scala,但是我想要使用build.sbtproject/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))

项目/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
2个回答

26
第一部分 - 设置集成测试在 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)

你只需要添加配置文件,然后就完成了。

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 目录下,该目录下包含 scalajavaresources 三个子目录,分别用于存放相关源码。

it配置中添加测试框架库,即在 build.sbt 文件中应类似于以下内容 - 注意 it 配置:

"org.specs2" %% "specs2" % "2.4.2" % "it"

重新加载sbt会话或重启它,it:test 应该可以使用Specs2测试执行所有位于 src/it/scala 下的测试。

为了缩小应执行的测试范围,请添加过滤器 - 确保它在具有 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”,但是,似乎没有它也可以工作,我不知道会引起什么问题,但目前还没有发现任何问题。 - Mike
使用Play 2.3.9,我按照示例操作,但我的IntegrationSpec.scala无法编译,因为找不到PlaySpecification,即类IntegrationSpec扩展了PlaySpecification。有任何想法为什么SBT没有将play libs包含在“it”阶段中?此外,我已将以下内容添加到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" - thlim
好的,我已经将play-test添加到"it"中,即 "com.typesafe.play" %% "play-test" % "2.3.9" % "it"。 - thlim
4
Play的集成测试文件夹是"src/it"而不是"/it",这很令人困惑,因为如果与“/app”和“/test”在基目录中并列将更有意义,就像Play解剖中所述一样。我通过在build.sbt中更改设置,将我的集成测试移动到那里,方法是将sourceDirectory in IntegrationTest := baseDirectory.value / "it"读取。然后它会找到通常的it/javait/scalait/resources目录。 - mikebridge
这是相当奇怪的命名建议 - 在不区分大小写的匹配中,UnitTest 也以 ItTest 结尾,并且 ItTest 解析为 IntegrationTestTest 的事实;-) - conny

13
这是我最终采用的方案,它使我能够:
  1. 将集成测试保留在play的/test目录中
  2. 运行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))

1
我真的很喜欢这个解决方案,因为我可以在任何选择的集成开发环境中克隆并使用它。如果我创建一个新的测试文件夹,那么从今天开始,我要么将 IDE 特定的内容放入我的构建过程中(令人不快),要么需要额外添加一个 IDE 步骤来告诉 IDE 关于我的新文件夹(也不太好)。 - rancidfishbreath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接