为啥在使用“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.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))

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/itscalajavaresources 目录下包含各自的来源。

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/javait/scalait/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 项目中的集成测试?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 PL/SQL 查询不使用 ODP.NET 执行

为啥我的 Qt 应用程序在执行时不显示 GUI?

为啥程序在登录时不执行segue?

为啥将结果添加到 List 时不执行方法调用?

为啥numpy在执行list方法时不创建数组

为啥数据库或语言平台在执行查询时不返回强类型类? [关闭]