单元测试 - 在 sbt 中使用自定义和插件的配置执行任务?



我有一个SBT项目,它有一个完整的构建定义和用于测试的自定义配置。

我添加了一个自带配置的插件,如果可能的话,我希望能够使用两种配置来执行任务。

如果不可能,我想把配置从插件拉到我的自定义配置。

的细节

我的自定义配置是unit,它用于将某些测试分类为单元测试,并且我想使用sbt-scoverage添加覆盖率。

我的完整构建定义包括:

lazy val UnitTest = config("unit") extend(Test)
def unitTestFilter(name: String) = name endsWith "UnitSpec"
lazy val myProject = Project(id="MyProject")
         .configs( UnitTest )
         .settings( inConfig(UnitTest)(Defaults.testTasks) : _*)
         .settings(
            testOptions in UnitTest := Seq(Tests.Filter(unitTestFilter)),
            parallelExecution in UnitTest := true
         )

为了执行单元测试,我运行sbt unit:test

我如何A)将sbt-scoverage添加到构建定义中的unit配置,或者B)在SBT运行中包括scoverageunit配置,例如sbt "unit,scoverage:test" ?

edit根据提供的2个答案,我正在接近我想要的。我现在遇到的问题是测试过滤器,并将其应用于配置。我已经更新了上面的原始代码片段,以包括我基于文件名使用的过滤器-参见项目部分中的testOptions以及我如何使用unitTestFilter。为了增加覆盖率,我添加了新的配置,用于覆盖率测试,所以现在有UnitTest, ComponentTest, CoverageUnitTestCoverageComponentTest。我现在的问题是,我不能得到测试选项/文件名过滤器传播到scoverage配置。

方法1:创建扩展scoverageTest的配置
lazy val CoverageUnitTest = config("coverUnit") extend (scoverageTest)
def unitTestFilter(name: String) = name endsWith "UnitSpec"
lazy val myProject = Project(id="MyProject")
     .configs( UnitTest, CoverageUnitTest )
     .settings(
        testOptions in CoverageUnitTest := Seq(Tests.Filter(unitTestFilter)),
        parallelExecution in CoverageUnitTest := true
     )

在上述方法中,不应用设置。如果我运行coverUnit:test,它执行组件和单元规格。我也尝试过使用testOptions in scoverageTest,它与过滤器一起工作,但问题是我在我的项目中有2个配置,即CoverageUnitTest和CoverageComponentTest,如果我使用in scoverageTest,那么只有1个过滤器适用于两个任务(即coverUnit:test和coverComponent:test都执行单元测试,或组件测试,基于顺序)。

方法2:扩展测试并增加仪器

lazy val CoverageUnitTest = config("coverUnit") extend (Test)
def unitTestFilter(name: String) = name endsWith "UnitSpec"
lazy val myProject = Project(id="MyProject")
     .configs( UnitTest, CoverageUnitTest )
     .settings( inConfig(CoverageUnitTest)(ScoverageSbtPlugin.instrumentSettings) : _* )
     .settings(
        testOptions in CoverageUnitTest := Seq(Tests.Filter(unitTestFilter)),
        parallelExecution in CoverageUnitTest := true
     )

同样,此方法不使用unitTestFilter过滤测试。

从查看ScoverageSbtPlugin源代码,看起来我可能需要以某种方式查看覆盖这: inConfig(scoverageTest)(Defaults.testSettings) ++,这是正确的方法吗?

编辑# 2这里有一个变通方法,使用方法1,使用CoverageUnitTest"替换为"scoverageTest":

lazy val dynamicTestFilter(name:String):Boolean = name endsWith scala.util.Properties.envOrElse("TEST_TYPE","UnitSpec")

run with TEST_TYPE=ComponentSpec sbt coverComponent:test

我用sbt 0.13.5-M2 :

> about
[info] This is sbt 0.13.5-M2
[info] The current project is {file:/Users/jacek/sandbox/so/sbt-scoverage-custom-config/}myProject 0.1-SNAPSHOT
[info] The current project is built against Scala 2.10.4
[info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, ScoverageSbtPlugin, scoverage.ScoverageSbtPlugin
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.4

除非我弄错了,否则您正在询问将scoverage设置应用于unit,因此执行unittest将与执行test:testscoverage设置相同。如果是,请继续往下读。否则,请告知。

我认为,你应该在构建定义中有以下内容(我选择build.sbt,这对我来说更简单):

scalaVersion := "2.10.4"
lazy val UnitTest = config("unit") extend(Test)
lazy val myProject = project
  .in(file("."))
  .configs(UnitTest)
  .settings(
    inConfig(UnitTest)(ScoverageSbtPlugin.instrumentSettings): _*
  )
  .settings(
    parallelExecution in UnitTest := true
  )

由于我对sbt-scoverage几乎一无所知,所以除了验证设置外,我无法确认其正确配置:

> unit:libraryDependencies
[info] List(org.scala-lang:scala-library:2.10.4, org.scoverage:scalac-scoverage-plugin:0.97.0:scoverage)
> test:libraryDependencies
[info] List(org.scala-lang:scala-library:2.10.4)

我没有检查这个,但是你可以试试。

lazy val UnitTest = config("unit") extend(Test)
lazy val myProject = Project(id="MyProject").
  configs(UnitTest, scoverage, scoverageTest).
  settings(ScoverageSbtPlugin.instrumentSettings: _*).
  settings(
    parallelExecution in UnitTest := true,
    sources in scoverageTest += (sources in UnitTest).value,
    sourceDirectory in scoverageTest += (sourceDirectory in UnitTest).value,
    unmanagedResources in scoverageTest += (unmanagedResources in UnitTest),
    resourceDirectory in scoverageTest += (resourceDirectory in UnitTest),
    externalDependencyClasspath in scoverageTest := Classpaths
      .concat((externalDependencyClasspath in scoverageTest).value, (externalDependencyClasspath in UnitTest).value)
  )

我将这两种建议结合起来使用,得出一个可行的配置。我使用了一个丑陋的hack,因为我不太确定如何停止配置继承,但这里或多或少是我所拥有的(我只展示了一个测试类型-单元-在这里,但我实际上有许多不同的类型。只有单元可以并行运行,组件/集成测试配置需要并行设置为false):

lazy val UnitTest = config("unit") extend(Test)
lazy val CoverageUnitTest = config("coverUnit") extend (scoverageTest)
def unitTestFilter(name: String) = name endsWith "UnitSpec"
def dynamicTestFilter(name:String): Boolean = name endsWith scala.util.Properties.envOrElse("TEST_TYPE","UnitSpec")
def determineParallel:Boolean = {
  scala.util.Properties.envOrElse("TEST_TYPE","UnitSpec") match {
    case testType:String if testType == "UnitSpec => true
    case _ => false
  }
}
lazy val myProject = Project(id="MyProject")
 .configs( UnitTest, CoverageUnitTest )
 .configs( ComponentTest, CoverageComponentTest )
 .settings( inConfig(UnitTest)(Defaults.testTasks) : _*)
 .settings(
   testOptions in UnitTest := Seq(Tests.Filter(unitTestFilter)),
   parallelExecution in UnitTest := true
 )
 .settings( inConfig(ComponentTest)(Defaults.testTasks) : _*)
 .settings(
   testOptions in ComponentTest := Seq(Tests.Filter(componentTestFilter)),
   parallelExecution in ComponentTest := false
 )
 .settings(
    testOptions in scoverageTest := Seq(Tests.Filter(unitTestFilter)),
    parallelExecution in scoverageTest := determineParallel
 )

第一组设置控制单元测试(无覆盖率),使用unit:test执行,第二组设置控制组件测试(component:test)。最后一个配置用于运行启用覆盖率的测试。scoverageTest配置用于单元和组件测试,但是我设置了一个系统属性,以便在运行SBT时使用一个标志来启用/禁用并行执行。

sbt coverUnit:test将使用scoverageTest配置执行单元测试并启用并行。$ TEST_TYPE=ComponentSpec sbt coverComponent:test在scoverageTest配置中执行组件测试,并通过determineParallel函数禁用并行执行。

最新更新