Skip to content

Commit 9843c58

Browse files
committed
manage BOMs in Tests
Starting with JUnit 5.12 and Spock 2.3 a BOM is available on Maven Central. If the version matches the BOMs will be automatically added. For JUnit, this has the effect that the platform-launcher is also managed in the BOM so it is actually not necessary to specify a platform-launcher-version. Hence the launcher is also added when the version is not set and the minimum version is met.
1 parent 8a196f9 commit 9843c58

File tree

5 files changed

+216
-35
lines changed

5 files changed

+216
-35
lines changed

libs/groovylib/package.mill

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import millbuild.*
77

88
object `package` extends MillPublishScalaModule with BuildInfo {
99

10-
def moduleDeps = Seq(build.libs.javalib, build.libs.javalib.testrunner, api)
10+
def moduleDeps = Seq(build.libs.util, build.libs.javalib, build.libs.javalib.testrunner, api)
1111
def localTestExtraModules: Seq[MillJavaModule] =
1212
super.localTestExtraModules ++ Seq(worker)
1313

libs/groovylib/src/mill/groovylib/GroovyModule.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import mill.*
1010
import mainargs.Flag
1111
import mill.api.daemon.internal.bsp.{BspBuildTarget, BspModuleApi}
1212
import mill.javalib.api.internal.{JavaCompilerOptions, JvmWorkerApi, ZincCompileJava}
13+
import mill.util.Version
1314

1415
/**
1516
* Core configuration required to compile a single Groovy module.
@@ -28,8 +29,18 @@ trait GroovyModule extends JavaModule with GroovyModuleApi { outer =>
2829
*/
2930
def groovyLanguageVersion: T[String] = Task { groovyVersion().split("[.]").take(2).mkString(".") }
3031

32+
private def isGroovyBomAvailable: T[Boolean] = Task {
33+
if (groovyVersion().isBlank) {
34+
false
35+
} else {
36+
Version.isAtLeast(groovyVersion(), "4.0.26")(using Version.IgnoreQualifierOrdering)
37+
}
38+
}
39+
3140
override def bomMvnDeps: T[Seq[Dep]] = super.bomMvnDeps() ++
32-
Seq(mvn"org.apache.groovy:groovy-bom:${groovyVersion()}")
41+
Seq(groovyVersion())
42+
.filter(_.nonEmpty && isGroovyBomAvailable())
43+
.map(v => mvn"org.apache.groovy:groovy-bom:$v")
3344

3445
/**
3546
* All individual source files fed into the compiler.

libs/groovylib/test/src/mill/groovylib/HelloGroovyTests.scala

Lines changed: 87 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package mill
22
package groovylib
33

44
import mill.javalib.{JavaModule, TestModule}
5-
import mill.api.{Task}
5+
import mill.api.Task
66
import mill.api.Discover
77
import mill.testkit.{TestRootModule, UnitTester}
88
import utest.*
@@ -11,6 +11,7 @@ object HelloGroovyTests extends TestSuite {
1111

1212
val groovy4Version = "4.0.28"
1313
val junit5Version = sys.props.getOrElse("TEST_JUNIT5_VERSION", "5.13.4")
14+
val spockGroovy4Version = "2.3-groovy-4.0"
1415

1516
object HelloGroovy extends TestRootModule {
1617

@@ -25,12 +26,8 @@ object HelloGroovyTests extends TestSuite {
2526
HelloGroovy.`groovy-tests`
2627
)
2728

28-
override def groovyVersion = groovy4Version
29-
override def depManagement = Seq(
30-
mvn"org.junit.jupiter:junit-jupiter-engine:$junit5Version"
31-
)
32-
override def jupiterVersion = junit5Version
33-
override def junitPlatformVersion = "1.13.4"
29+
override def groovyVersion: T[String] = groovy4Version
30+
override def jupiterVersion: T[String] = junit5Version
3431
}
3532

3633
}
@@ -40,38 +37,53 @@ object HelloGroovyTests extends TestSuite {
4037
override def mainClass = Some("jointcompile.JavaMain")
4138
}
4239

40+
object deps extends Module {
41+
42+
object groovyBom extends GroovyModule {
43+
override def groovyVersion: T[String] = groovy4Version
44+
}
45+
46+
object groovyNoBom extends GroovyModule {
47+
// Groovy-BOM available starting with 4.0.26
48+
override def groovyVersion: T[String] = "4.0.25"
49+
}
50+
51+
object `spockBom` extends GroovyModule with TestModule.Spock {
52+
override def spockVersion: T[String] = spockGroovy4Version
53+
override def groovyVersion: T[String] = groovy4Version
54+
}
55+
56+
object `spockNoBom` extends GroovyModule with TestModule.Spock {
57+
// Groovy-BOM available starting with 2.3
58+
override def spockVersion: T[String] = "2.2-groovy-4.0"
59+
override def groovyVersion: T[String] = groovy4Version
60+
}
61+
62+
}
63+
4364
trait Test extends GroovyModule {
4465

4566
override def mainClass = Some("hello.Hello")
4667

4768
object test extends GroovyTests with TestModule.Junit5 {
48-
override def depManagement = Seq(
49-
mvn"org.junit.jupiter:junit-jupiter-engine:5.13.4"
50-
)
51-
override def jupiterVersion = "5.13.4"
69+
override def jupiterVersion: T[String] = junit5Version
5270
override def junitPlatformVersion = "1.13.4"
5371
}
5472

5573
object script extends GroovyModule {
56-
override def groovyVersion = "4.0.28"
74+
override def groovyVersion: T[String] = groovy4Version
5775
override def mainClass = Some("HelloScript")
5876
}
5977

6078
object staticcompile extends GroovyModule {
61-
override def groovyVersion = "4.0.28"
79+
override def groovyVersion: T[String] = groovy4Version
6280
override def mainClass = Some("hellostatic.HelloStatic")
6381
}
6482

6583
object spock extends GroovyTests with TestModule.Spock {
66-
override def junitPlatformVersion = "1.13.4"
67-
override def spockVersion = "2.3-groovy-4.0"
68-
override def groovyVersion = "4.0.28"
69-
70-
def bomMvnDeps = Seq(
71-
mvn"org.junit:junit-bom:5.13.4",
72-
// mvn"org.apache.groovy:groovy-bom:${groovyVersion()}",
73-
mvn"org.spockframework:spock-bom:${spockVersion()}"
74-
)
84+
override def jupiterVersion: T[String] = junit5Version
85+
override def spockVersion: T[String] = spockGroovy4Version
86+
override def groovyVersion: T[String] = groovy4Version
7587
}
7688
}
7789
object main extends Test {
@@ -91,6 +103,7 @@ object HelloGroovyTests extends TestSuite {
91103
def m = HelloGroovy.main
92104
def mixed = HelloGroovy.`groovy-tests`
93105
def joint = HelloGroovy.`joint-compile`
106+
def deps = HelloGroovy.deps
94107

95108
test("running a Groovy script") {
96109
testEval().scoped { eval =>
@@ -183,5 +196,57 @@ object HelloGroovyTests extends TestSuite {
183196
}
184197
}
185198

199+
test("dependency management") {
200+
201+
test("groovy") {
202+
203+
val groovyBom = mvn"org.apache.groovy:groovy-bom:$groovy4Version"
204+
205+
test("groovy bom is added when version is at least 4.0.26") {
206+
testEval().scoped { eval =>
207+
val Right(result) = eval.apply(deps.groovyBom.bomMvnDeps): @unchecked
208+
209+
assert(
210+
result.value.contains(groovyBom)
211+
)
212+
}
213+
}
214+
215+
test("groovy bom is NOT added when version is below 4.0.26") {
216+
testEval().scoped { eval =>
217+
val Right(result) = eval.apply(deps.groovyNoBom.bomMvnDeps): @unchecked
218+
219+
assert(
220+
!result.value.contains(groovyBom)
221+
)
222+
}
223+
}
224+
}
225+
226+
test("spock") {
227+
228+
val spockBom = mvn"org.spockframework:spock-bom:$spockGroovy4Version"
229+
230+
test("spock bom is added when version is at least 2.3") {
231+
testEval().scoped { eval =>
232+
val Right(result) = eval.apply(deps.spockBom.bomMvnDeps): @unchecked
233+
234+
assert(
235+
result.value.contains(spockBom)
236+
)
237+
}
238+
}
239+
240+
test("spock bom is NOT added when version is below 2.3") {
241+
testEval().scoped { eval =>
242+
val Right(result) = eval.apply(deps.spockNoBom.bomMvnDeps): @unchecked
243+
244+
assert(
245+
!result.value.contains(spockBom)
246+
)
247+
}
248+
}
249+
}
250+
}
186251
}
187252
}

libs/javalib/src/mill/javalib/TestModule.scala

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import mill.api.Task
99
import mill.api.TaskCtx
1010
import mill.api.DefaultTaskModule
1111
import mill.javalib.bsp.BspModule
12-
import mill.util.Jvm
12+
import mill.util.{Jvm, Version}
1313
import mill.api.JsonFormatters.given
1414
import mill.constants.EnvVars
1515
import mill.javalib.testrunner.{
@@ -358,24 +358,53 @@ object TestModule {
358358
* You can override the [[junitPlatformVersion]] and [[jupiterVersion]] task
359359
* or provide the JUnit 5-dependencies yourself.
360360
*
361+
* In case the [[jupiterVersion]] is set (and it is > 5.12), it pulls in JUnit-BOM in [[bomMvnDeps]]. If this is
362+
* true, then there is no need to specify the [[junitPlatformVersion]] anymore, because this is managed by the
363+
* BOM.
364+
*
361365
* See: https://junit.org/junit5/
362366
*/
363367
trait Junit5 extends TestModule {
364368

365-
/** The JUnit 5 Platfrom version to use, or empty, if you want to provide the dependencies yourself. */
369+
/** The JUnit 5 Platform version to use, or empty, if you want to provide the dependencies yourself. */
366370
def junitPlatformVersion: T[String] = Task { "" }
367371

368-
/** The JUnit Jupiter version to use, or empty, if you want to provide the dependencie yourself. */
372+
/** The JUnit Jupiter version to use, or empty, if you want to provide the dependencies yourself. */
369373
def jupiterVersion: T[String] = Task { "" }
370374

375+
private def isJupiterBomAvailable: T[Boolean] = Task {
376+
if (jupiterVersion().isBlank) {
377+
false
378+
} else {
379+
Version.isAtLeast(jupiterVersion(), "5.12.0")(using Version.IgnoreQualifierOrdering)
380+
}
381+
}
382+
371383
override def testFramework: T[String] = "com.github.sbt.junit.jupiter.api.JupiterFramework"
372384

385+
override def bomMvnDeps: T[Seq[Dep]] = Task {
386+
super.bomMvnDeps() ++
387+
Seq(jupiterVersion())
388+
.filter(!_.isBlank() && isJupiterBomAvailable())
389+
.flatMap(v =>
390+
Seq(
391+
mvn"org.junit:junit-bom:${v.trim()}"
392+
)
393+
)
394+
}
395+
373396
override def mandatoryMvnDeps: T[Seq[Dep]] = Task {
374397
super.mandatoryMvnDeps() ++
375398
Seq(mvn"${mill.javalib.api.Versions.jupiterInterface}") ++
376-
Seq(junitPlatformVersion())
377-
.filter(!_.isBlank())
378-
.map(v => mvn"org.junit.platform:junit-platform-launcher:${v.trim()}") ++
399+
Seq(junitPlatformVersion()).flatMap(v => {
400+
if (!v.isBlank) {
401+
Some(mvn"org.junit.platform:junit-platform-launcher:${v.trim()}")
402+
} else if (isJupiterBomAvailable()) {
403+
Some(mvn"org.junit.platform:junit-platform-launcher")
404+
} else {
405+
None
406+
}
407+
}) ++
379408
Seq(jupiterVersion())
380409
.filter(!_.isBlank())
381410
.map(v => mvn"org.junit.jupiter:junit-jupiter-api:${v.trim()}")
@@ -603,6 +632,9 @@ object TestModule {
603632
/**
604633
* TestModule that uses Spock Test Framework to run tests.
605634
* You can override the [[spockVersion]] task or provide the Spock dependency yourself.
635+
*
636+
* In case the version is set, it pulls in Spock-BOM in [[bomMvnDeps]] (only for 2.3 onwards)
637+
* and Spock-Core in [[mvnDeps]]
606638
*/
607639
trait Spock extends TestModule.Junit5 {
608640

@@ -611,12 +643,24 @@ object TestModule {
611643
""
612644
}
613645

614-
/** The Groovy version to use, or the empty string, if you want to provide the Groovy test dependency yourself. */
615-
def groovyVersion: T[String] = Task {
616-
""
646+
private def isSpockBomAvailable: T[Boolean] = Task {
647+
if (spockVersion().isBlank) {
648+
false
649+
} else {
650+
Version.isAtLeast(spockVersion(), "2.3")(using Version.IgnoreQualifierOrdering)
651+
}
617652
}
618653

619-
// TODO currently bomMvnDeps not in JavaModuleBase so we cannot pull in the Spock-BOM
654+
override def bomMvnDeps: T[Seq[Dep]] = Task {
655+
super.bomMvnDeps() ++
656+
Seq(spockVersion())
657+
.filter(!_.isBlank() && isSpockBomAvailable())
658+
.flatMap(v =>
659+
Seq(
660+
mvn"org.spockframework:spock-bom:${v.trim()}"
661+
)
662+
)
663+
}
620664

621665
override def mandatoryMvnDeps: T[Seq[Dep]] = Task {
622666
super.mandatoryMvnDeps() ++
@@ -650,6 +694,7 @@ object TestModule {
650694
def mvnDeps: T[Seq[Dep]] = Seq()
651695
def mandatoryMvnDeps: T[Seq[Dep]] = Seq()
652696
def resources: T[Seq[PathRef]] = Task { Seq.empty[PathRef] }
697+
def bomMvnDeps: T[Seq[Dep]] = Seq()
653698
}
654699

655700
trait ScalaModuleBase extends mill.Module {

0 commit comments

Comments
 (0)