【问题标题】:Executing task with custom and plugin's configs in sbt?在 sbt 中使用自定义和插件的配置执行任务?
【发布时间】:2014-05-04 15:13:03
【问题描述】:

我有一个 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 个答案,我正在接近我想要的。我现在遇到的问题是测试过滤器,并将其应用于配置。我已经更新了上面的原始代码 sn-p 以包含我使用的基于文件名的过滤器 - 请参阅项目部分中的 testOptions 以及我如何使用 unitTestFilter。为了增加覆盖率,我为覆盖率测试添加了新配置,所以现在有UnitTestComponentTestCoverageUnitTestCoverageComponentTest。我现在遇到的问题是我无法让测试选项/文件名过滤器传播到覆盖配置。

方法 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:扩展测试并在instrumentation中添加

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运行

【问题讨论】:

  • 虽然我回复了,但我仍然不确定。 “将 sbt-scoverage 添加到构建定义中的单元配置”是什么意思??您将如何验证您的构建配置是否满足要求?
  • 基本上想运行unit:test 并从中获得覆盖率报告。我不介意创建一个新配置,例如unitcoverage,这将允许我运行 sbt unitscoverage:test 来运行我的单元测试和覆盖率报告。

标签: unit-testing sbt scoverage


【解决方案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,因此执行 unittest 将等同于执行 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
  )

我对@9​​87654330@ 几乎一无所知,除了验证设置之外,我无法确认其正确配置:

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

【讨论】:

  • 感谢 Jacek,我已经试了一下,它几乎就在那里 - 添加 ScoverageSbtPlugin.instrumentSettings。但是,我已经更新了我原来的帖子,指出我遇到的另一个问题。我需要根据文件名过滤要运行的测试。上面的方法 2 涵盖了这种方法,你能看到一个简单的方法来应用过滤器吗?
【解决方案2】:

我没有检查这个,但这里有一些你可以尝试的。

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

【讨论】:

  • 嗨,尤金,感谢您的回复。我尝试了这种方法 - 根据 Jacek 的回复,在我的配置中使用 instrumentSettings 就足够了,而无需执行所有 scoverageTest 的事情。但是,我正在努力让测试过滤器正常工作。为了过滤测试,我的方法是否有任何过于明显的地方?
【解决方案3】:

我结合使用这两种建议来提出一个可行的配置。我使用了 1 个丑陋的 hack,因为我不太确定如何停止配置继承,但这里或多或少是我所拥有的(我只显示 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)。最后一个配置用于在启用覆盖率的情况下运行测试。 scoverageTest 配置用于单元测试和组件测试,但我设置了系统属性以在运行 SBT 时使用标志来启用/禁用并行执行。

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

【讨论】:

  • 必须使用环境变量一点也不优雅,但适用于我的用例。
猜你喜欢
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-06
  • 2014-06-03
  • 2015-11-23
  • 2023-04-01
  • 2014-04-17
相关资源
最近更新 更多