Skip to content

Commit f761c0f

Browse files
authored
Update to JUnit 5.13 and refactor minimum version detection scheme (#375)
* Update to JUnit 5.13.0 * Use first-party types for Gradle & AGP version Remove the need for a third-party semver parsing library * AGP 8.10.1, 8.12 Alpha 3
1 parent cbfe9ff commit f761c0f

File tree

8 files changed

+92
-56
lines changed

8 files changed

+92
-56
lines changed

build-logic/src/main/kotlin/Dependencies.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
object libs {
44
object versions {
55
const val kotlin = "2.1.21"
6-
const val junitJupiter = "5.13.0-RC1"
7-
const val junitVintage = "5.13.0-RC1"
8-
const val junitPlatform = "1.13.0-RC1"
6+
const val junitJupiter = "5.13.0"
7+
const val junitVintage = "5.13.0"
8+
const val junitPlatform = "1.13.0"
99

1010
const val composeBom = "2025.03.00"
1111
const val androidXMultidex = "2.0.1"
@@ -19,7 +19,6 @@ object libs {
1919
const val coroutines = "1.10.2"
2020
const val dokka = "2.0.0"
2121
const val espresso = "3.6.1"
22-
const val javaSemver = "0.10.2"
2322
const val junit4 = "4.13.2"
2423
const val konfToml = "1.1.2"
2524
const val kotlinxBinaryCompatibilityValidator = "0.17.0"
@@ -51,7 +50,6 @@ object libs {
5150

5251
const val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}"
5352
const val kotlinCoroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}"
54-
const val javaSemver = "com.github.zafarkhaja:java-semver:${versions.javaSemver}"
5553

5654
const val junitJupiterApi = "org.junit.jupiter:junit-jupiter-api:${versions.junitJupiter}"
5755
const val junitJupiterParams = "org.junit.jupiter:junit-jupiter-params:${versions.junitJupiter}"

build-logic/src/main/kotlin/Environment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ enum class SupportedAgp(
1717
AGP_8_7("8.7.3", gradle = "8.9"),
1818
AGP_8_8("8.8.2", gradle = "8.10.2"),
1919
AGP_8_9("8.9.3", gradle = "8.11.1"),
20-
AGP_8_10("8.10.0", gradle = "8.11.1"),
20+
AGP_8_10("8.10.1", gradle = "8.11.1"),
2121
AGP_8_11("8.11.0-alpha10", gradle = "8.13"),
22-
AGP_8_12("8.12.0-alpha01", gradle = "8.13")
22+
AGP_8_12("8.12.0-alpha03", gradle = "8.13")
2323
;
2424

2525
companion object {

plugin/android-junit5/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ dependencies {
9999

100100
implementation(gradleApi())
101101
implementation(libs.kotlinStdLib)
102-
implementation(libs.javaSemver)
103102
implementation(libs.junitPlatformCommons)
104103

105104
testImplementation(gradleTestKit())

plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/AndroidJUnitPlatformPlugin.kt

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package de.mannodermaus.gradle.plugins.junit5
22

3-
import com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
43
import de.mannodermaus.gradle.plugins.junit5.dsl.AndroidJUnitPlatformExtension.Companion.createJUnit5Extension
54
import de.mannodermaus.gradle.plugins.junit5.internal.config.MIN_REQUIRED_AGP_VERSION
65
import de.mannodermaus.gradle.plugins.junit5.internal.config.MIN_REQUIRED_GRADLE_VERSION
76
import de.mannodermaus.gradle.plugins.junit5.internal.config.PluginConfig
87
import de.mannodermaus.gradle.plugins.junit5.internal.configureJUnit5
98
import de.mannodermaus.gradle.plugins.junit5.internal.extensions.whenAndroidPluginAdded
109
import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireGradle
11-
import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireVersion
10+
import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireAgp
1211
import org.gradle.api.Plugin
1312
import org.gradle.api.Project
13+
import org.gradle.util.GradleVersion
1414

1515
/**
1616
* Android JUnit Platform plugin for Gradle.
@@ -19,21 +19,23 @@ import org.gradle.api.Project
1919
public class AndroidJUnitPlatformPlugin : Plugin<Project> {
2020

2121
override fun apply(project: Project) {
22-
requireGradle(MIN_REQUIRED_GRADLE_VERSION) {
23-
"android-junit5 plugin requires Gradle $MIN_REQUIRED_GRADLE_VERSION or later"
24-
}
25-
26-
requireVersion(
27-
actual = ANDROID_GRADLE_PLUGIN_VERSION,
28-
required = MIN_REQUIRED_AGP_VERSION
22+
requireGradle(
23+
actual = GradleVersion.current(),
24+
required = MIN_REQUIRED_GRADLE_VERSION
2925
) {
30-
"android-junit5 plugin requires Android Gradle Plugin $MIN_REQUIRED_AGP_VERSION or later"
26+
"android-junit5 plugin requires Gradle $MIN_REQUIRED_GRADLE_VERSION or later"
3127
}
3228

3329
project.whenAndroidPluginAdded { plugin ->
34-
val extension = project.createJUnit5Extension()
35-
val config = PluginConfig.find(project, plugin)
36-
if (config != null) {
30+
PluginConfig.find(project, plugin)?.let { config ->
31+
requireAgp(
32+
actual = config.currentAgpVersion,
33+
required = MIN_REQUIRED_AGP_VERSION
34+
) {
35+
"android-junit5 plugin requires Android Gradle Plugin $MIN_REQUIRED_AGP_VERSION or later"
36+
}
37+
38+
val extension = project.createJUnit5Extension()
3739
configureJUnit5(project, config, extension)
3840
}
3941
}

plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/Constants.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
package de.mannodermaus.gradle.plugins.junit5.internal.config
44

5-
internal const val MIN_REQUIRED_GRADLE_VERSION = "8.2" // When updating this, check buildSrc/Tasks.kt and update it there, too
6-
internal const val MIN_REQUIRED_AGP_VERSION = "8.2.0"
5+
import com.android.build.api.AndroidPluginVersion
6+
import org.gradle.util.GradleVersion
7+
8+
// When updating this, check buildSrc/Tasks.kt and update it there, too
9+
internal val MIN_REQUIRED_GRADLE_VERSION = GradleVersion.version("8.2")
10+
internal val MIN_REQUIRED_AGP_VERSION = AndroidPluginVersion(8, 2)
711

812
internal const val EXTENSION_NAME = "junitPlatform"
913

plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ private constructor(
5050
val hasJacocoPlugin get() = project.plugins.hasPlugin("jacoco")
5151
private val hasKotlinPlugin get() = project.plugins.findPlugin("kotlin-android") != null
5252

53+
val currentAgpVersion get() = componentsExtension.pluginVersion
54+
5355
fun finalizeDsl(block: (CommonExtension<*, *, *, *, *>) -> Unit) {
5456
componentsExtension.finalizeDsl(block)
5557
}
Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package de.mannodermaus.gradle.plugins.junit5.internal.utils
22

3-
import com.github.zafarkhaja.semver.Version
3+
import com.android.build.api.AndroidPluginVersion
44
import org.gradle.api.GradleException
55
import org.gradle.util.GradleVersion
66

@@ -9,16 +9,14 @@ internal fun excludedPackagingOptions() = listOf(
99
"/META-INF/LICENSE-notice.md"
1010
)
1111

12-
internal fun requireGradle(version: String, message: () -> String) {
13-
require(GradleVersion.current() >= GradleVersion.version(version)) {
12+
internal fun requireGradle(actual: GradleVersion, required: GradleVersion, message: () -> String) {
13+
require(actual >= required) {
1414
throw GradleException(message())
1515
}
1616
}
1717

18-
internal fun requireVersion(actual: String, required: String, message: () -> String) {
19-
val actualVersion = Version.parse(actual)
20-
val requiredVersion = Version.parse(required)
21-
require(actualVersion.isHigherThanOrEquivalentTo(requiredVersion)) {
18+
internal fun requireAgp(actual: AndroidPluginVersion, required: AndroidPluginVersion, message: () -> String) {
19+
require(actual >= required) {
2220
throw GradleException(message())
2321
}
2422
}
Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package de.mannodermaus.gradle.plugins.junit5
22

3+
import com.android.build.api.AndroidPluginVersion
34
import com.google.common.truth.Truth.assertThat
45
import de.mannodermaus.gradle.plugins.junit5.internal.config.MIN_REQUIRED_AGP_VERSION
5-
import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireVersion
6+
import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireAgp
67
import org.junit.jupiter.params.ParameterizedTest
78
import org.junit.jupiter.params.provider.CsvSource
89

@@ -14,39 +15,71 @@ import org.junit.jupiter.params.provider.CsvSource
1415
class VersionCheckerTests {
1516

1617
@CsvSource(
17-
"7.0.0-alpha01, false",
18-
"7.0.0-alpha01, false",
19-
"7.0.0-beta01, false",
20-
"7.0.0-rc01, false",
21-
"7.0.0, false",
22-
"8.0.0-beta01, false",
23-
"8.0.0, false",
24-
"8.0.1, false",
25-
"8.0.1-alpha01, false",
26-
"8.1.0, false",
27-
"8.1.0-beta01, false",
28-
"8.2.0, true",
29-
"8.3.0-rc01, true",
30-
"8.4.0-alpha05, true",
31-
"8.10.1-alpha01, true",
32-
"8.10.0, true",
33-
"8.11.0-beta01, true",
34-
"8.11.0, true",
18+
"7.0.0-alpha1, false",
19+
"7.0.0-alpha1, false",
20+
"7.0.0-beta1, false",
21+
"7.0.0-rc1, false",
22+
"7.0.0, false",
23+
"8.0.0-beta1, false",
24+
"8.0.0, false",
25+
"8.0.1, false",
26+
"8.0.1-alpha1, false",
27+
"8.1.0, false",
28+
"8.1.0-beta1, false",
29+
"8.2.0, true",
30+
"8.3.0-rc1, true",
31+
"8.4.0-alpha5, true",
32+
"8.10.1-alpha11, true",
33+
"8.10.0, true",
34+
"8.11.0-beta1, true",
35+
"8.11.0, true",
3536
)
3637
@ParameterizedTest
3738
fun `check AGP compatibility`(version: String, compatible: Boolean) {
38-
assertThat(versionCompatible(version)).isEqualTo(compatible)
39+
val pluginVersion = version.toAndroidPluginVersion()
40+
assertThat(versionCompatible(pluginVersion)).isEqualTo(compatible)
3941
}
4042

41-
private fun versionCompatible(version: String): Boolean {
43+
private fun versionCompatible(version: AndroidPluginVersion): Boolean {
4244
return try {
43-
requireVersion(
44-
actual = version,
45-
required = MIN_REQUIRED_AGP_VERSION,
46-
message = { "" })
45+
requireAgp(
46+
actual = version,
47+
required = MIN_REQUIRED_AGP_VERSION,
48+
message = { "" }
49+
)
4750
true
48-
} catch (error: Throwable) {
51+
} catch (_: Throwable) {
4952
false
5053
}
5154
}
55+
56+
private fun String.toAndroidPluginVersion(): AndroidPluginVersion {
57+
// Split into stable and optional preview parts
58+
val firstSplit = split('-')
59+
60+
// Split first part further into major, minor, patch
61+
val stableComponents = firstSplit[0].split('.')
62+
63+
var version = AndroidPluginVersion(
64+
major = stableComponents[0].toInt(),
65+
minor = stableComponents[1].toInt(),
66+
micro = stableComponents.getOrNull(2)?.toInt() ?: 0
67+
)
68+
69+
// Attach preview part
70+
val preview = firstSplit.getOrNull(1)
71+
72+
version = when {
73+
preview == null -> version
74+
preview.startsWith("alpha") -> version.alpha(preview.substringAfter("alpha").toInt())
75+
preview.startsWith("beta") -> version.beta(preview.substringAfter("beta").toInt())
76+
preview.startsWith("rc") -> version.rc(preview.substringAfter("rc").toInt())
77+
else -> version
78+
}
79+
80+
// Validate correctness
81+
assertThat(version.toString()).endsWith(this)
82+
83+
return version
84+
}
5285
}

0 commit comments

Comments
 (0)