在sbt中使用自定义和插件的配置执行任务?

时间:2014-03-26 09:55:56

标签: unit-testing sbt scoverage

我有一个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"

编辑根据提供的2个答案,我接近我想要的。我现在遇到的问题是测试过滤器,并将其应用于配置。我已更新上面的原始代码段,以包含我根据文件名使用的过滤器 - 请参阅项目部分中的testOptions以及我如何使用unitTestFilter。为了增加覆盖率,我为Coverage测试添加了新的配置,现在有UnitTestComponentTestCoverageUnitTestCoverageComponentTest。我现在的问题是我无法将测试选项/文件名过滤器传播到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:根据订单测试执行单元测试或组件测试)。

方法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")

使用TEST_TYPE=ComponentSpec sbt coverComponent:test

运行

3 个答案:

答案 0 :(得分:1)

我使用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,以便执行unit的{​​{1}}与执行test相同加上test:test设置。如果是这样,请继续阅读。否则,请告知。

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

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

答案 1 :(得分:1)

我没有检查过这个但是你可以尝试一下。

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)
  )

答案 2 :(得分:0)

我使用两种建议的组合来提出工作配置。我使用的是一个丑陋的黑客,因为我不太确定如何停止配置继承,但这里或多或少都是我所拥有的(我只显示1种测试类型 - 单位 - 这里,但实际上我有许多不同的类型。只有单元可以并行运行,组件/集成测试配置需要并行设置为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)。最后一个配置用于在启用coverage的情况下运行测试。 scoverageTest配置用于单元和组件测试,但我设置了一个系统属性,以便在运行SBT时使用标志来启用/禁用并行执行。

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