覆盖率:结合测试范围和测试范围

时间:2019-01-24 14:53:12

标签: scala sbt code-coverage scoverage

我使用过滤器拆分了单元测试和集成测试:

  lazy val FunTest = config("it") extend Test

  def funTestFilter(name: String): Boolean = name endsWith "Spec"

  def unitTestFilter(name: String): Boolean = name endsWith "Test"

  ...
  testOptions in Test := Seq(Tests.Filter(unitTestFilter)),
  testOptions in FunTest := Seq(Tests.Filter(funTestFilter)),
  ...

所以我可以做这样的事情:

sbt clean coverage test dockerComposeUp it:test dockerComposeStop coverageReport

可悲的是杀死了我的所有承保范围,只有生成的BuildInfo拥有承保范围。

仅使用sbt clean coverage test coverageReportsbt clean coverage it:test coverageReport即可正常工作。

可以在这里找到整个项目:https://github.com/pme123/play-binding-form

保障范围版本:1.5.1

2 个答案:

答案 0 :(得分:8)

SBT支持增量编译,但是Scoverage不支持增量编译。 Scoverage会在编译开始之前清除检测信息,并每次都从头开始检测过程。启用“覆盖”的所有类的子集的编译将导致错误的覆盖率报告。

在这种情况下,sbt-buldinfo模块中已启用server插件。它注册源生成器,该源生成器在每次编译之前执行并生成server/target/scala_2.12/src_managed/main/sbt-buildinfo/BuildInfo.scala文件。

SBT BuildInfo插件足够聪明,仅在内容更改时才可以重新生成此文件,但是由于BuildInfoOption.BuildTime包含在buildInfoOptions设置中, 每次编译前都会重新生成此文件。

在编译过程中,编译器每次都会找到一个修改后的文件(BuildInfo.scala),并开始对此文件进行增量编译。 Scoverage清除其先前的检测信息,并仅保存有关BuildInfo.scala文件的信息。

对于像sbt clean coverage test dockerComposeUp it:test dockerComposeStop coverageReport这样的执行,第一个编译过程是test任务的一部分,第二个编译过程是it:test任务的一部分。这就是为什么单独使用它们时没有问题。

Docker与我们的问题无关。

要解决该问题,至少在启用覆盖率的情况下,必须防止每次编译时BuildInfo.scala文件的重新生成。 我是通过这样修改project/Settings.scala文件来做到这一点的:

  private lazy val buildInfoSettings = Seq(

    buildInfoKeys := Seq[BuildInfoKey](name, version, scalaVersion, sbtVersion),

    buildInfoOptions ++= { if (coverageEnabled.value) Seq() else Seq(BuildInfoOption.BuildTime) }, // <-- this line was changed
    buildInfoOptions += BuildInfoOption.ToJson,

    buildInfoPackage := "pme123.adapters.version"
  )

buildInfoOptions不包括BuildTime选项,当覆盖范围打开时。

它看起来并不精妙,但可以。您可能会找到更好的方法。

答案 1 :(得分:5)

您可以使用自己的构建时间,而不必根据阶段使用不同的buildinfo对象,这可能会导致编译错误。

lazy val buildTime: SettingKey[String] = SettingKey[String]("buildTime", "time of build")

ThisBuild / buildTime := ZonedDateTime.now(ZoneOffset.UTC).toString

buildInfoKeys :=
  Seq[BuildInfoKey](
    name,
    version,
    scalaVersion,
    sbtVersion,
    buildTime
  )

这应该可以解决此问题。 我在我的一个项目中有此配置,因为我想更好地控制日期的格式化方式,而且没有相同的问题