From ba1cceb04b07c6b874e1eb9fe36d496415e5419d Mon Sep 17 00:00:00 2001 From: Tomasz Godzik Date: Tue, 15 Sep 2026 17:52:49 +0200 Subject: [PATCH] improvement: Set fork to true automatically for Scala 3 --- .../scala/scoverage/ScoverageSbtPlugin.scala | 15 +++++++++++---- .../scoverage/scala3-repeat-coverage/build.sbt | 14 ++++++++++++++ .../scala3-repeat-coverage/project/plugins.sbt | 9 +++++++++ .../src/main/scala/GoodCoverage.scala | 7 +++++++ .../src/main/scala/two/GoodCoverage.scala | 9 +++++++++ .../src/test/scala/GoodCoverageSpec.scala | 17 +++++++++++++++++ .../scoverage/scala3-repeat-coverage/test | 18 ++++++++++++++++++ 7 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 src/sbt-test/scoverage/scala3-repeat-coverage/build.sbt create mode 100644 src/sbt-test/scoverage/scala3-repeat-coverage/project/plugins.sbt create mode 100644 src/sbt-test/scoverage/scala3-repeat-coverage/src/main/scala/GoodCoverage.scala create mode 100644 src/sbt-test/scoverage/scala3-repeat-coverage/src/main/scala/two/GoodCoverage.scala create mode 100644 src/sbt-test/scoverage/scala3-repeat-coverage/src/test/scala/GoodCoverageSpec.scala create mode 100644 src/sbt-test/scoverage/scala3-repeat-coverage/test diff --git a/src/main/scala/scoverage/ScoverageSbtPlugin.scala b/src/main/scala/scoverage/ScoverageSbtPlugin.scala index 3913a7d7..2678957c 100644 --- a/src/main/scala/scoverage/ScoverageSbtPlugin.scala +++ b/src/main/scala/scoverage/ScoverageSbtPlugin.scala @@ -83,7 +83,7 @@ object ScoverageSbtPlugin extends AutoPlugin { case _ => defaultScoverageVersion } } - ) ++ coverageSettings ++ scalacSettings + ) ++ coverageSettings ++ scalacSettings ++ coverageTestRuntimeSettings(Test) private def isScala2(scalaVersion: String) = CrossVersion @@ -203,9 +203,6 @@ object ScoverageSbtPlugin extends AutoPlugin { coverageEnabled.value && isScala3SupportingScoverage(scalaVersion.value) ) { Seq( - Some( - s"-coverage-out:${new java.io.File(coverageDataDir.value, "scoverage-data").getAbsolutePath}" - ), excludedPackages .collect { case v @@ -234,6 +231,16 @@ object ScoverageSbtPlugin extends AutoPlugin { } ) + // See https://github.com/scoverage/sbt-scoverage/issues/522 + private def coverageTestRuntimeSettings( + config: Configuration + ): Seq[Setting[_]] = + Seq( + config / fork := coverageEnabled.value && isScala3SupportingScoverage( + scalaVersion.value + ) + ) + private def scalacRuntime(deps: Seq[ModuleID]): String = { scalacRuntimeArtifact + optionalScalaJsSuffix(deps) } diff --git a/src/sbt-test/scoverage/scala3-repeat-coverage/build.sbt b/src/sbt-test/scoverage/scala3-repeat-coverage/build.sbt new file mode 100644 index 00000000..29525f06 --- /dev/null +++ b/src/sbt-test/scoverage/scala3-repeat-coverage/build.sbt @@ -0,0 +1,14 @@ +version := "0.1" + +scalaVersion := "3.9.0" + +libraryDependencies += "org.scalameta" %% "munit" % "1.0.1" % Test + +coverageMinimumStmtTotal := 100 +coverageMinimumBranchTotal := 100 +coverageMinimumStmtPerPackage := 100 +coverageMinimumBranchPerPackage := 100 +coverageMinimumStmtPerFile := 100 +coverageMinimumBranchPerFile := 100 + +coverageFailOnMinimum := true diff --git a/src/sbt-test/scoverage/scala3-repeat-coverage/project/plugins.sbt b/src/sbt-test/scoverage/scala3-repeat-coverage/project/plugins.sbt new file mode 100644 index 00000000..4361ea41 --- /dev/null +++ b/src/sbt-test/scoverage/scala3-repeat-coverage/project/plugins.sbt @@ -0,0 +1,9 @@ +val pluginVersion = sys.props.getOrElse( + "plugin.version", + throw new RuntimeException( + """|The system property 'plugin.version' is not defined. + |Specify this property using the scriptedLaunchOpts -D.""".stripMargin + ) +) + +addSbtPlugin("org.scoverage" % "sbt-scoverage" % pluginVersion) diff --git a/src/sbt-test/scoverage/scala3-repeat-coverage/src/main/scala/GoodCoverage.scala b/src/sbt-test/scoverage/scala3-repeat-coverage/src/main/scala/GoodCoverage.scala new file mode 100644 index 00000000..ac6582bb --- /dev/null +++ b/src/sbt-test/scoverage/scala3-repeat-coverage/src/main/scala/GoodCoverage.scala @@ -0,0 +1,7 @@ +object GoodCoverage { + + def sum(num1: Int, num2: Int) = { + if (0 == num1) num2 else if (0 == num2) num1 else num1 + num2 + } + +} diff --git a/src/sbt-test/scoverage/scala3-repeat-coverage/src/main/scala/two/GoodCoverage.scala b/src/sbt-test/scoverage/scala3-repeat-coverage/src/main/scala/two/GoodCoverage.scala new file mode 100644 index 00000000..587e11e1 --- /dev/null +++ b/src/sbt-test/scoverage/scala3-repeat-coverage/src/main/scala/two/GoodCoverage.scala @@ -0,0 +1,9 @@ +package two + +object GoodCoverage { + + def sum(num1: Int, num2: Int) = { + if (0 == num1) num2 else if (0 == num2) num1 else num1 + num2 + } + +} diff --git a/src/sbt-test/scoverage/scala3-repeat-coverage/src/test/scala/GoodCoverageSpec.scala b/src/sbt-test/scoverage/scala3-repeat-coverage/src/test/scala/GoodCoverageSpec.scala new file mode 100644 index 00000000..df8d4374 --- /dev/null +++ b/src/sbt-test/scoverage/scala3-repeat-coverage/src/test/scala/GoodCoverageSpec.scala @@ -0,0 +1,17 @@ +import munit.FunSuite + +class GoodCoverageSpec extends FunSuite { + + test("GoodCoverage should sum two numbers") { + assertEquals(GoodCoverage.sum(1, 2), 3) + assertEquals(GoodCoverage.sum(0, 3), 3) + assertEquals(GoodCoverage.sum(3, 0), 3) + } + + test("two.GoodCoverage should sum two numbers") { + assertEquals(two.GoodCoverage.sum(1, 2), 3) + assertEquals(two.GoodCoverage.sum(0, 3), 3) + assertEquals(two.GoodCoverage.sum(3, 0), 3) + } + +} diff --git a/src/sbt-test/scoverage/scala3-repeat-coverage/test b/src/sbt-test/scoverage/scala3-repeat-coverage/test new file mode 100644 index 00000000..1b2c7d50 --- /dev/null +++ b/src/sbt-test/scoverage/scala3-repeat-coverage/test @@ -0,0 +1,18 @@ +# https://github.com/scoverage/sbt-scoverage/issues/522 +# Scala 3 coverage in a single sbt session used to report 0% after the first +# `clean; coverage; test` because measurement files were not rewritten. +> clean +> coverage +> test +> coverageReport +$ exists target/scala-3.5.0/scoverage-data +> clean +> coverage +> test +> coverageReport +$ exists target/scala-3.5.0/scoverage-data +# coverage stays enabled; a third clean/test cycle should still record coverage +> clean +> test +> coverageReport +$ exists target/scala-3.5.0/scoverage-data