From 48cd4efbd2fc970a24267798bdd806bac09b29ab Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Tue, 30 Sep 2025 20:07:33 +0900 Subject: [PATCH 1/8] Update to Java 17, Kotlin 2.2, JUnit 6.0.0 --- build-logic/src/main/kotlin/Dependencies.kt | 22 ++++++++++----------- build-logic/src/main/kotlin/Tasks.kt | 2 +- plugin/android-junit5/build.gradle.kts | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/build-logic/src/main/kotlin/Dependencies.kt b/build-logic/src/main/kotlin/Dependencies.kt index 5afae149..1eea61ef 100644 --- a/build-logic/src/main/kotlin/Dependencies.kt +++ b/build-logic/src/main/kotlin/Dependencies.kt @@ -2,12 +2,10 @@ object libs { object versions { - const val kotlin = "2.1.21" - const val junitJupiter = "5.14.0" - const val junitVintage = "5.14.0" - const val junitPlatform = "1.14.0" + const val kotlin = "2.2.20" + const val junitFramework = "6.0.0" - const val composeBom = "2025.03.00" + const val composeBom = "2025.09.01" const val androidXMultidex = "2.0.1" const val androidXTestAnnotation = "1.0.1" const val androidXTestCore = "1.6.1" @@ -51,13 +49,13 @@ object libs { const val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}" const val kotlinCoroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}" - const val junitJupiterApi = "org.junit.jupiter:junit-jupiter-api:${versions.junitJupiter}" - const val junitJupiterParams = "org.junit.jupiter:junit-jupiter-params:${versions.junitJupiter}" - const val junitJupiterEngine = "org.junit.jupiter:junit-jupiter-engine:${versions.junitJupiter}" - const val junitVintageEngine = "org.junit.vintage:junit-vintage-engine:${versions.junitVintage}" - const val junitPlatformCommons = "org.junit.platform:junit-platform-commons:${versions.junitPlatform}" - const val junitPlatformLauncher = "org.junit.platform:junit-platform-launcher:${versions.junitPlatform}" - const val junitPlatformRunner = "org.junit.platform:junit-platform-runner:${versions.junitPlatform}" + const val junitJupiterApi = "org.junit.jupiter:junit-jupiter-api:${versions.junitFramework}" + const val junitJupiterParams = "org.junit.jupiter:junit-jupiter-params:${versions.junitFramework}" + const val junitJupiterEngine = "org.junit.jupiter:junit-jupiter-engine:${versions.junitFramework}" + const val junitVintageEngine = "org.junit.vintage:junit-vintage-engine:${versions.junitFramework}" + const val junitPlatformCommons = "org.junit.platform:junit-platform-commons:${versions.junitFramework}" + const val junitPlatformLauncher = "org.junit.platform:junit-platform-launcher:${versions.junitFramework}" + const val junitPlatformRunner = "org.junit.platform:junit-platform-runner:${versions.junitFramework}" const val apiguardianApi = "org.apiguardian:apiguardian-api:${versions.apiGuardian}" const val composeBom = "androidx.compose:compose-bom:${versions.composeBom}" diff --git a/build-logic/src/main/kotlin/Tasks.kt b/build-logic/src/main/kotlin/Tasks.kt index 1b747a71..8976c707 100644 --- a/build-logic/src/main/kotlin/Tasks.kt +++ b/build-logic/src/main/kotlin/Tasks.kt @@ -34,7 +34,7 @@ fun Project.configureTestResources() { "TARGET_SDK_VERSION" to Android.targetSdkVersion.toString(), "KOTLIN_VERSION" to libs.versions.kotlin, - "JUNIT_JUPITER_VERSION" to libs.versions.junitJupiter, + "JUNIT_JUPITER_VERSION" to libs.versions.junitFramework, "JUNIT5_ANDROID_LIBS_VERSION" to Artifacts.Instrumentation.Core.latestStableVersion, // Collect all supported AGP versions into a single string. diff --git a/plugin/android-junit5/build.gradle.kts b/plugin/android-junit5/build.gradle.kts index a87352ae..91c2b3ac 100644 --- a/plugin/android-junit5/build.gradle.kts +++ b/plugin/android-junit5/build.gradle.kts @@ -21,7 +21,7 @@ plugins { // // The other way around ("call Kotlin from Groovy") is prohibited explicitly. // ------------------------------------------------------------------------------------------------ -val javaVersion = JavaVersion.VERSION_11.toString() +val javaVersion = JavaVersion.VERSION_17.toString() tasks.withType { compilerOptions.jvmTarget.set(JvmTarget.fromTarget(javaVersion)) } From 805e1d5f0ce1666d93bd8bad04e9322504757818 Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Tue, 30 Sep 2025 20:30:05 +0900 Subject: [PATCH 2/8] Update instrumentation to JUnit 6.0.0, raising its minimum API level to 35 --- build-logic/src/main/kotlin/Dependencies.kt | 2 +- instrumentation/CHANGELOG.md | 3 +++ instrumentation/compose/build.gradle.kts | 13 ++++++----- instrumentation/core/build.gradle.kts | 5 +++-- .../junit5/ActivityScenarioExtension.kt | 8 +++---- .../de/mannodermaus/junit5/CoreConstants.kt | 4 ++-- .../internal/DisabledOnSdkVersionCondition.kt | 3 ++- .../internal/EnabledOnSdkVersionCondition.kt | 3 ++- .../DisabledOnSdkVersionConditionTests.kt | 12 +++++----- .../DisabledOnSdkVersionIntegrationTests.kt | 2 +- .../EnabledOnSdkVersionConditionTests.kt | 16 +++++++------- .../EnabledOnSdkVersionIntegrationTests.kt | 2 +- instrumentation/extensions/build.gradle.kts | 2 +- .../extensions/GrantPermissionExtension.kt | 8 +++++-- .../GrantPermissionExtensionTests.kt | 2 +- instrumentation/runner/build.gradle.kts | 6 +++-- .../junit5/AndroidJUnit5Builder.kt | 18 +++++++-------- .../internal/discovery/EmptyTestPlan.kt | 21 ++++++++---------- .../internal/discovery/GeneratedFilters.kt | 4 ++-- .../internal/discovery/ParsedSelectors.kt | 4 ++-- .../internal/dummy/JupiterTestMethodFinder.kt | 5 +++-- .../internal/formatters/TestNameFormatter.kt | 2 ++ ...roidJUnit5.kt => AndroidJUnitFramework.kt} | 9 +++----- .../AndroidJUnitPlatformRunnerListener.kt | 2 +- .../runners/AndroidJUnitPlatformTestTree.kt | 13 ++++------- ...{DummyJUnit5.kt => DummyJUnitFramework.kt} | 22 ++++++++++++++----- .../internal/runners/JUnit5RunnerFactory.kt | 12 +++++----- .../dummy/JupiterTestMethodFinderTests.kt | 4 ++-- .../internal/runners/AndroidJUnit5Tests.kt | 2 +- instrumentation/sample/build.gradle.kts | 13 ++++++----- instrumentation/testutil/build.gradle.kts | 5 +++-- 31 files changed, 124 insertions(+), 103 deletions(-) rename instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/{AndroidJUnit5.kt => AndroidJUnitFramework.kt} (93%) rename instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/{DummyJUnit5.kt => DummyJUnitFramework.kt} (51%) diff --git a/build-logic/src/main/kotlin/Dependencies.kt b/build-logic/src/main/kotlin/Dependencies.kt index 1eea61ef..c826f50c 100644 --- a/build-logic/src/main/kotlin/Dependencies.kt +++ b/build-logic/src/main/kotlin/Dependencies.kt @@ -55,7 +55,7 @@ object libs { const val junitVintageEngine = "org.junit.vintage:junit-vintage-engine:${versions.junitFramework}" const val junitPlatformCommons = "org.junit.platform:junit-platform-commons:${versions.junitFramework}" const val junitPlatformLauncher = "org.junit.platform:junit-platform-launcher:${versions.junitFramework}" - const val junitPlatformRunner = "org.junit.platform:junit-platform-runner:${versions.junitFramework}" + const val junitPlatformSuiteApi = "org.junit.platform:junit-platform-suite-api:${versions.junitFramework}" const val apiguardianApi = "org.apiguardian:apiguardian-api:${versions.apiGuardian}" const val composeBom = "androidx.compose:compose-bom:${versions.composeBom}" diff --git a/instrumentation/CHANGELOG.md b/instrumentation/CHANGELOG.md index 5508ee38..196ddef6 100644 --- a/instrumentation/CHANGELOG.md +++ b/instrumentation/CHANGELOG.md @@ -3,6 +3,9 @@ Change Log ## Unreleased +- Update to Kotlin 2.2 +- Raise minimum supported API level to 35, acknowledging the baseline shift to Java 17 in JUnit 6 + ## 1.8.0 (2025-06-11) - Compile with SDK 35 diff --git a/instrumentation/compose/build.gradle.kts b/instrumentation/compose/build.gradle.kts index 673a3144..e0ba2fac 100644 --- a/instrumentation/compose/build.gradle.kts +++ b/instrumentation/compose/build.gradle.kts @@ -1,5 +1,6 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("com.android.library") @@ -9,7 +10,13 @@ plugins { id("org.jetbrains.kotlin.plugin.compose") } -val javaVersion = JavaVersion.VERSION_11 +val javaVersion = JavaVersion.VERSION_17 + +kotlin { + compilerOptions { + jvmTarget = JvmTarget.fromTarget(javaVersion.toString()) + } +} android { namespace = "de.mannodermaus.junit5.compose" @@ -33,10 +40,6 @@ android { targetCompatibility = javaVersion } - kotlinOptions { - jvmTarget = javaVersion.toString() - } - testOptions { unitTests.isReturnDefaultValues = true targetSdk = Android.targetSdkVersion diff --git a/instrumentation/core/build.gradle.kts b/instrumentation/core/build.gradle.kts index 4dbc036e..8bad778f 100644 --- a/instrumentation/core/build.gradle.kts +++ b/instrumentation/core/build.gradle.kts @@ -10,7 +10,7 @@ plugins { id("de.mannodermaus.android-junit5").version(Artifacts.Plugin.latestStableVersion) } -val javaVersion = JavaVersion.VERSION_11 +val javaVersion = JavaVersion.VERSION_17 android { namespace = "de.mannodermaus.junit5" @@ -94,7 +94,8 @@ dependencies { // This is required by the "instrumentation-runner" companion library, // since it can't provide any JUnit 5 runtime libraries itself // due to fear of prematurely incrementing the minSdkVersion requirement. - runtimeOnly(libs.junitPlatformRunner) + runtimeOnly(libs.junitPlatformLauncher) + runtimeOnly(libs.junitPlatformSuiteApi) runtimeOnly(libs.junitJupiterEngine) // This transitive dependency of JUnit 5 is required to be on the runtime classpath, diff --git a/instrumentation/core/src/main/java/de/mannodermaus/junit5/ActivityScenarioExtension.kt b/instrumentation/core/src/main/java/de/mannodermaus/junit5/ActivityScenarioExtension.kt index 43b06212..202a8b39 100644 --- a/instrumentation/core/src/main/java/de/mannodermaus/junit5/ActivityScenarioExtension.kt +++ b/instrumentation/core/src/main/java/de/mannodermaus/junit5/ActivityScenarioExtension.kt @@ -5,6 +5,7 @@ import android.app.Activity import android.content.Intent import android.os.Build import android.util.Log +import androidx.annotation.RequiresApi import androidx.test.core.app.ActivityScenario import de.mannodermaus.junit5.ActivityScenarioExtension.Companion.launch import de.mannodermaus.junit5.internal.LOG_TAG @@ -110,7 +111,7 @@ import java.util.concurrent.locks.ReentrantLock * ``` * */ -@TargetApi(Build.VERSION_CODES.O) +@RequiresApi(Build.VERSION_CODES.O) public class ActivityScenarioExtension private constructor(private val scenarioSupplier: () -> ActivityScenario) : BeforeEachCallback, AfterEachCallback, ParameterResolver { @@ -194,7 +195,6 @@ private constructor(private val scenarioSupplier: () -> ActivityScenario) : B /* Private */ - @Suppress("InconsistentCommentForJavaParameter") private fun ExtensionContext.acquireLock(state: Boolean) { // No need to do anything unless parallelism is enabled if (executionMode != ExecutionMode.CONCURRENT) { @@ -209,7 +209,7 @@ private constructor(private val scenarioSupplier: () -> ActivityScenario) : B // Create a global lock for restricting test execution to one-by-one; // this is necessary to ensure that only one ActivityScenario is ever active at a time, // preventing violations of Android's instrumentation and Espresso - val lock = store.getOrComputeIfAbsent( + val lock = store.computeIfAbsent( /* key = */ LOCK_KEY, /* defaultCreator = */ { ReentrantLock() }, /* requiredType = */ ReentrantLock::class.java, @@ -223,7 +223,7 @@ private constructor(private val scenarioSupplier: () -> ActivityScenario) : B } private fun logConcurrentExecutionWarningOnce(store: ExtensionContext.Store) { - store.getOrComputeIfAbsent(WARNING_KEY) { + store.computeIfAbsent(WARNING_KEY) { setOf( " [WARNING!] UI tests using ActivityScenarioExtension should not be executed in CONCURRENT mode.", " We will try to disable parallelism for Espresso tests, but this may be error-prone", diff --git a/instrumentation/core/src/main/java/de/mannodermaus/junit5/CoreConstants.kt b/instrumentation/core/src/main/java/de/mannodermaus/junit5/CoreConstants.kt index 0127049e..025c46af 100644 --- a/instrumentation/core/src/main/java/de/mannodermaus/junit5/CoreConstants.kt +++ b/instrumentation/core/src/main/java/de/mannodermaus/junit5/CoreConstants.kt @@ -1,7 +1,7 @@ package de.mannodermaus.junit5 /** - * The minimum Android API level on which JUnit 5 tests may be executed. + * The minimum Android API level on which JUnit Framework tests may be executed. * Trying to launch a test on an older device will simply mark it as 'skipped'. */ -public const val JUNIT5_MINIMUM_SDK_VERSION: Int = 26 +public const val JUNIT5_MINIMUM_SDK_VERSION: Int = 35 diff --git a/instrumentation/core/src/main/java/de/mannodermaus/junit5/internal/DisabledOnSdkVersionCondition.kt b/instrumentation/core/src/main/java/de/mannodermaus/junit5/internal/DisabledOnSdkVersionCondition.kt index c77deccd..405ceceb 100644 --- a/instrumentation/core/src/main/java/de/mannodermaus/junit5/internal/DisabledOnSdkVersionCondition.kt +++ b/instrumentation/core/src/main/java/de/mannodermaus/junit5/internal/DisabledOnSdkVersionCondition.kt @@ -2,6 +2,7 @@ package de.mannodermaus.junit5.internal import android.annotation.TargetApi import android.os.Build +import androidx.annotation.RequiresApi import de.mannodermaus.junit5.condition.DisabledOnSdkVersion import de.mannodermaus.junit5.internal.EnabledOnSdkVersionCondition.Companion.disabled import de.mannodermaus.junit5.internal.EnabledOnSdkVersionCondition.Companion.enabled @@ -18,7 +19,7 @@ internal class DisabledOnSdkVersionCondition : ExecutionCondition { ConditionEvaluationResult.enabled("@DisabledOnSdkVersion is not present") } - @TargetApi(24) + @RequiresApi(24) override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult { val optional = findAnnotation(context.element, DisabledOnSdkVersion::class.java) diff --git a/instrumentation/core/src/main/java/de/mannodermaus/junit5/internal/EnabledOnSdkVersionCondition.kt b/instrumentation/core/src/main/java/de/mannodermaus/junit5/internal/EnabledOnSdkVersionCondition.kt index 895df623..df3c16b7 100644 --- a/instrumentation/core/src/main/java/de/mannodermaus/junit5/internal/EnabledOnSdkVersionCondition.kt +++ b/instrumentation/core/src/main/java/de/mannodermaus/junit5/internal/EnabledOnSdkVersionCondition.kt @@ -2,6 +2,7 @@ package de.mannodermaus.junit5.internal import android.annotation.TargetApi import android.os.Build +import androidx.annotation.RequiresApi import de.mannodermaus.junit5.condition.EnabledOnSdkVersion import org.junit.jupiter.api.extension.ConditionEvaluationResult import org.junit.jupiter.api.extension.ExecutionCondition @@ -24,7 +25,7 @@ internal class EnabledOnSdkVersionCondition : ExecutionCondition { } } - @TargetApi(24) + @RequiresApi(24) override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult { val optional = findAnnotation(context.element, EnabledOnSdkVersion::class.java) diff --git a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionConditionTests.kt b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionConditionTests.kt index 3daa5bf6..83565733 100644 --- a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionConditionTests.kt +++ b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionConditionTests.kt @@ -38,10 +38,10 @@ class DisabledOnSdkVersionConditionTests : AbstractExecutionConditionTests() { */ @Test fun disabledBecauseMinApiIsMatched() { - withApiLevel(26) { + withApiLevel(35) { evaluateCondition() assertDisabled() - assertReasonEquals("Disabled on API 26") + assertReasonEquals("Disabled on API 35") } } @@ -62,10 +62,10 @@ class DisabledOnSdkVersionConditionTests : AbstractExecutionConditionTests() { */ @Test fun disabledBecauseApiIsInValidRange() { - withApiLevel(26) { + withApiLevel(35) { evaluateCondition() assertDisabled() - assertReasonEquals("Disabled on API 26") + assertReasonEquals("Disabled on API 35") } } @@ -74,10 +74,10 @@ class DisabledOnSdkVersionConditionTests : AbstractExecutionConditionTests() { */ @Test fun enabledBecauseMinApiLowEnough() { - withApiLevel(26) { + withApiLevel(35) { evaluateCondition() assertEnabled() - assertReasonEquals("Enabled on API 26") + assertReasonEquals("Enabled on API 35") } } diff --git a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionIntegrationTests.kt b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionIntegrationTests.kt index 6cef4f62..0796e3e3 100644 --- a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionIntegrationTests.kt +++ b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionIntegrationTests.kt @@ -23,7 +23,7 @@ class DisabledOnSdkVersionIntegrationTests { } @Disabled("Used by DisabledOnSdkVersionConditionTests only") - @DisabledOnSdkVersion(until = 26) + @DisabledOnSdkVersion(until = 35) @Test fun disabledBecauseMaxApiIsMatched() { } diff --git a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionConditionTests.kt b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionConditionTests.kt index ea72c6b1..b5aee965 100644 --- a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionConditionTests.kt +++ b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionConditionTests.kt @@ -37,10 +37,10 @@ class EnabledOnSdkVersionConditionTests : AbstractExecutionConditionTests() { */ @Test fun enabledBecauseMinApiIsMatched() { - withApiLevel(26) { + withApiLevel(35) { evaluateCondition() assertEnabled() - assertReasonEquals("Enabled on API 26") + assertReasonEquals("Enabled on API 35") } } @@ -61,10 +61,10 @@ class EnabledOnSdkVersionConditionTests : AbstractExecutionConditionTests() { */ @Test fun enabledBecauseApiIsInValidRange() { - withApiLevel(26) { + withApiLevel(35) { evaluateCondition() assertEnabled() - assertReasonEquals("Enabled on API 26") + assertReasonEquals("Enabled on API 35") } } @@ -73,10 +73,10 @@ class EnabledOnSdkVersionConditionTests : AbstractExecutionConditionTests() { */ @Test fun disabledBecauseMinApiTooLow() { - withApiLevel(26) { + withApiLevel(35) { evaluateCondition() assertDisabled() - assertReasonEquals("Disabled on API 26") + assertReasonEquals("Disabled on API 35") } } @@ -97,10 +97,10 @@ class EnabledOnSdkVersionConditionTests : AbstractExecutionConditionTests() { */ @Test fun disabledBecauseApiIsOutsideValidRange() { - withApiLevel(26) { + withApiLevel(35) { evaluateCondition() assertDisabled() - assertReasonEquals("Disabled on API 26") + assertReasonEquals("Disabled on API 35") } } } diff --git a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionIntegrationTests.kt b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionIntegrationTests.kt index 64fce9c2..f777e2a7 100644 --- a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionIntegrationTests.kt +++ b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionIntegrationTests.kt @@ -23,7 +23,7 @@ class EnabledOnSdkVersionIntegrationTests { } @Disabled("Used by EnabledOnSdkVersionConditionTests only") - @EnabledOnSdkVersion(until = 26) + @EnabledOnSdkVersion(until = 35) @Test fun enabledBecauseMaxApiIsMatched() { } diff --git a/instrumentation/extensions/build.gradle.kts b/instrumentation/extensions/build.gradle.kts index 0759bd5d..35745738 100644 --- a/instrumentation/extensions/build.gradle.kts +++ b/instrumentation/extensions/build.gradle.kts @@ -27,7 +27,7 @@ apply { plugin("de.mannodermaus.android-junit5") } -val javaVersion = JavaVersion.VERSION_11 +val javaVersion = JavaVersion.VERSION_17 android { namespace = "de.mannodermaus.junit5.extensions" diff --git a/instrumentation/extensions/src/main/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtension.kt b/instrumentation/extensions/src/main/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtension.kt index 057ea63c..e50bf435 100644 --- a/instrumentation/extensions/src/main/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtension.kt +++ b/instrumentation/extensions/src/main/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtension.kt @@ -64,9 +64,13 @@ internal constructor(private val permissionGranter: PermissionGranter) : BeforeE permissionGranter.addPermissions(*permissionSet.toTypedArray()) } + internal fun beforeEach() { + permissionGranter.requestPermissions() + } + /* BeforeEachCallback */ - override fun beforeEach(context: ExtensionContext?) { - permissionGranter.requestPermissions() + override fun beforeEach(context: ExtensionContext) { + beforeEach() } } diff --git a/instrumentation/extensions/src/test/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtensionTests.kt b/instrumentation/extensions/src/test/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtensionTests.kt index f1a264c3..b83f9f4e 100644 --- a/instrumentation/extensions/src/test/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtensionTests.kt +++ b/instrumentation/extensions/src/test/kotlin/de/mannodermaus/junit5/extensions/GrantPermissionExtensionTests.kt @@ -82,7 +82,7 @@ class GrantPermissionExtensionTests { private fun runExtension(vararg permissions: String) { val extension = GrantPermissionExtension(granter) extension.grantPermissions(permissions) - extension.beforeEach(null) + extension.beforeEach() } private class TestPermissionGranter : PermissionGranter { diff --git a/instrumentation/runner/build.gradle.kts b/instrumentation/runner/build.gradle.kts index dfc8bb50..62f38010 100644 --- a/instrumentation/runner/build.gradle.kts +++ b/instrumentation/runner/build.gradle.kts @@ -26,7 +26,7 @@ apply { plugin("de.mannodermaus.android-junit5") } -val javaVersion = JavaVersion.VERSION_11 +val javaVersion = JavaVersion.VERSION_17 android { namespace = "de.mannodermaus.junit5.runner" @@ -99,10 +99,12 @@ dependencies { // by the "instrumentation" companion library instead. compileOnly(libs.junitJupiterApi) compileOnly(libs.junitJupiterParams) - compileOnly(libs.junitPlatformRunner) + compileOnly(libs.junitPlatformLauncher) + compileOnly(libs.junitPlatformSuiteApi) testImplementation(project(":testutil")) testImplementation(libs.robolectric) + testImplementation(libs.junitPlatformLauncher) testRuntimeOnly(libs.junitJupiterEngine) } diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/AndroidJUnit5Builder.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/AndroidJUnit5Builder.kt index dcb05d09..bde0153f 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/AndroidJUnit5Builder.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/AndroidJUnit5Builder.kt @@ -4,7 +4,7 @@ import android.util.Log import de.mannodermaus.junit5.internal.LOG_TAG import de.mannodermaus.junit5.internal.LibcoreAccess import de.mannodermaus.junit5.internal.runners.AndroidJUnit5RunnerParams -import de.mannodermaus.junit5.internal.runners.tryCreateJUnit5Runner +import de.mannodermaus.junit5.internal.runners.tryCreateJUnitFrameworkRunner import org.junit.runner.Runner import org.junit.runners.model.RunnerBuilder @@ -33,18 +33,18 @@ import org.junit.runners.model.RunnerBuilder @Suppress("unused") public class AndroidJUnit5Builder : RunnerBuilder() { - private val junit5Available by lazy { + private val junitFrameworkAvailable by lazy { try { // The verification order of this block is quite important. // Do not change it without thorough testing of potential consequences! - // After tampering with this, verify that integration - // with applications using JUnit 5 for UI tests still works, - // AND that integration with applications NOT using JUnit 5 for UI tests still works. + // After tampering with this, verify that integration with applications + // using JUnit Framework for UI tests AND applications NOT using JUnit Framework + // for UI tests still works. // // First, verify the existence of junit-jupiter-api on the classpath. - // Then, verify that the Android JUnit 5 Runner is available. + // Then, verify that the Android JUnit Framework Runner is available. Class.forName("org.junit.jupiter.api.Test") - Class.forName("de.mannodermaus.junit5.internal.runners.AndroidJUnit5") + Class.forName("de.mannodermaus.junit5.internal.runners.AndroidJUnitFramework") true } catch (e: Throwable) { false @@ -66,8 +66,8 @@ public class AndroidJUnit5Builder : RunnerBuilder() { if (testClass.isInIgnorablePackage) return null try { - return if (junit5Available) { - tryCreateJUnit5Runner(testClass) { params } + return if (junitFrameworkAvailable) { + tryCreateJUnitFrameworkRunner(testClass) { params } } else { null } diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/EmptyTestPlan.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/EmptyTestPlan.kt index 585cadda..da82d9ab 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/EmptyTestPlan.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/EmptyTestPlan.kt @@ -2,37 +2,34 @@ package de.mannodermaus.junit5.internal.discovery import androidx.annotation.RequiresApi import org.junit.platform.engine.ConfigurationParameters +import org.junit.platform.engine.OutputDirectoryCreator import org.junit.platform.engine.TestDescriptor -import org.junit.platform.engine.reporting.OutputDirectoryProvider import org.junit.platform.launcher.TestPlan import java.io.File import java.util.Optional /** * A JUnit TestPlan that does absolutely nothing. - * Used by [de.mannodermaus.junit5.internal.runners.AndroidJUnit5] whenever a class + * Used by [de.mannodermaus.junit5.internal.runners.AndroidJUnitFramework] whenever a class * is not loadable through the JUnit Platform and should be discarded. */ -@RequiresApi(26) +@RequiresApi(35) internal object EmptyTestPlan : TestPlan( false, emptyConfigurationParameters, emptyOutputDirectoryProvider ) -@RequiresApi(26) +@RequiresApi(35) private val emptyConfigurationParameters = object : ConfigurationParameters { - override fun get(key: String?) = Optional.empty() - override fun getBoolean(key: String?) = Optional.empty() + override fun get(key: String) = Optional.empty() + override fun getBoolean(key: String) = Optional.empty() override fun keySet() = emptySet() - - @Deprecated("Deprecated in Java", ReplaceWith("keySet().size")) - override fun size() = 0 } -@RequiresApi(26) -private val emptyOutputDirectoryProvider = object : OutputDirectoryProvider { +@RequiresApi(35) +private val emptyOutputDirectoryProvider = object : OutputDirectoryCreator { private val path = File.createTempFile("empty-output", ".nop").toPath() override fun getRootDirectory() = path - override fun createOutputDirectory(testDescriptor: TestDescriptor?) = path + override fun createOutputDirectory(testDescriptor: TestDescriptor) = path } diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/GeneratedFilters.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/GeneratedFilters.kt index d8d14293..e7a7738e 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/GeneratedFilters.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/GeneratedFilters.kt @@ -2,7 +2,7 @@ package de.mannodermaus.junit5.internal.discovery import android.content.Context import android.content.res.Resources -import de.mannodermaus.junit5.internal.runners.AndroidJUnit5 +import de.mannodermaus.junit5.internal.runners.AndroidJUnitFramework import org.junit.platform.engine.Filter import org.junit.platform.launcher.TagFilter @@ -11,7 +11,7 @@ private const val INSTRUMENTATION_FILTER_RES_FILE_NAME = "de_mannodermaus_junit5 /** * Holder object for the filters of a test plan. * It converts the contents of a resource file into JUnit Platform [Filter] objects - * for the [AndroidJUnit5] runner. + * for the [AndroidJUnitFramework] runner. */ internal object GeneratedFilters { diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/ParsedSelectors.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/ParsedSelectors.kt index d0b4684c..74ef8f0c 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/ParsedSelectors.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/discovery/ParsedSelectors.kt @@ -1,7 +1,7 @@ package de.mannodermaus.junit5.internal.discovery import android.os.Bundle -import de.mannodermaus.junit5.internal.runners.AndroidJUnit5 +import de.mannodermaus.junit5.internal.runners.AndroidJUnitFramework import org.junit.platform.engine.DiscoverySelector import org.junit.platform.engine.discovery.DiscoverySelectors @@ -9,7 +9,7 @@ import org.junit.platform.engine.discovery.DiscoverySelectors * Holder object for the selectors of a test plan. * It converts the arguments handed to the Runner by the * Android instrumentation into JUnit Platform [DiscoverySelector] objects - * for the [AndroidJUnit5] runner. + * for the [AndroidJUnitFramework] runner. */ internal object ParsedSelectors { diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/dummy/JupiterTestMethodFinder.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/dummy/JupiterTestMethodFinder.kt index 69daac7c..250019b2 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/dummy/JupiterTestMethodFinder.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/dummy/JupiterTestMethodFinder.kt @@ -12,8 +12,9 @@ import java.lang.reflect.Modifier /** * Algorithm to find all methods annotated with a JUnit Jupiter annotation - * for devices running below API level 26 (i.e. those that cannot run Jupiter). - * We're unable to rely on JUnit Platform's own reflection utilities since they rely on Java 8 stuff + * for devices running below API level 35 (i.e. those that cannot run Jupiter). + * We're unable to rely on JUnit Platform's own reflection utilities, + * since they rely on new Java APIs that are unavailable on this device */ internal object JupiterTestMethodFinder { private val jupiterTestAnnotations = listOf( diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/formatters/TestNameFormatter.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/formatters/TestNameFormatter.kt index 99c76ab8..fce06fb0 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/formatters/TestNameFormatter.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/formatters/TestNameFormatter.kt @@ -42,9 +42,11 @@ internal object TestNameFormatter { // - Cut off no-parameter brackets '()' // - Replace any other round brackets with square brackets (for parameterized tests) // to ensure that logs are displayed in the test results window (ref. #350) + // - Remove quotation marks (for parameterized tests) return identifier.displayName .replace("()", "") .replace('(', '[') .replace(')', ']') + .replace("\"", "") } } diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitFramework.kt similarity index 93% rename from instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5.kt rename to instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitFramework.kt index b5d2b5ae..767e5df7 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitFramework.kt @@ -5,24 +5,21 @@ import androidx.annotation.VisibleForTesting import de.mannodermaus.junit5.internal.discovery.EmptyTestPlan import de.mannodermaus.junit5.internal.runners.notification.ParallelRunNotifier import org.junit.platform.commons.JUnitException -import org.junit.platform.engine.ConfigurationParameters import org.junit.platform.engine.discovery.MethodSelector -import org.junit.platform.launcher.TestPlan import org.junit.platform.launcher.core.LauncherFactory import org.junit.runner.Runner import org.junit.runner.notification.RunNotifier -import java.util.Optional /** * JUnit Runner implementation using the JUnit Platform as its backbone. - * Serves as an intermediate solution to writing JUnit 5-based instrumentation tests + * Serves as an intermediate solution to writing JUnit Framework-based instrumentation tests * until official support arrives for this. * * @see org.junit.platform.runner.JUnitPlatform */ -@RequiresApi(26) +@RequiresApi(35) @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) -internal class AndroidJUnit5( +internal class AndroidJUnitFramework( private val testClass: Class<*>, paramsSupplier: () -> AndroidJUnit5RunnerParams = AndroidJUnit5RunnerParams.Companion::create, ) : Runner() { diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformRunnerListener.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformRunnerListener.kt index c5197d3d..038bee42 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformRunnerListener.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformRunnerListener.kt @@ -22,7 +22,7 @@ internal class AndroidJUnitPlatformRunnerListener( private val notifier: RunNotifier ) : TestExecutionListener { - override fun reportingEntryPublished(testIdentifier: TestIdentifier?, entry: ReportEntry?) { + override fun reportingEntryPublished(testIdentifier: TestIdentifier, entry: ReportEntry) { // No-op, but must be declared to avoid AbstractMethodError } diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformTestTree.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformTestTree.kt index 35d72980..b9809bee 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformTestTree.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnitPlatformTestTree.kt @@ -161,7 +161,7 @@ internal class AndroidJUnitPlatformTestTree( } else if (source is MethodSource) { val methodParameterTypes = source.methodParameterTypes - return if (methodParameterTypes.isBlank()) { + return if (methodParameterTypes.isNullOrBlank()) { source.methodName } else { String.format("%s(%s)", source.methodName, methodParameterTypes) @@ -184,10 +184,10 @@ internal class AndroidJUnitPlatformTestTree( TestPlan( /* containsTests = */ delegate.containsTests(), /* configurationParameters = */ delegate.configurationParameters, - /* outputDirectoryProvider = */ delegate.outputDirectoryProvider + /* outputDirectoryCreator = */ delegate.outputDirectoryCreator ) { - fun getRealParent(child: TestIdentifier?): Optional { + fun getRealParent(child: TestIdentifier): Optional { // Because the overridden "getParent()" from the superclass is modified, // expose this additional method to access the actual parent identifier of the given child. // This is needed when composing the display name of a dynamic test. @@ -216,7 +216,7 @@ internal class AndroidJUnitPlatformTestTree( /* Unchanged */ - override fun addInternal(testIdentifier: TestIdentifier?) { + override fun addInternal(testIdentifier: TestIdentifier) { delegate.addInternal(testIdentifier) } @@ -232,11 +232,6 @@ internal class AndroidJUnitPlatformTestTree( return delegate.getChildren(parentId) } - @Suppress("OVERRIDE_DEPRECATION") - override fun getChildren(parentId: String): Set { - return delegate.getChildren(parentId) - } - override fun getTestIdentifier(uniqueId: UniqueId): TestIdentifier { return delegate.getTestIdentifier(uniqueId) } diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/DummyJUnit5.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/DummyJUnitFramework.kt similarity index 51% rename from instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/DummyJUnit5.kt rename to instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/DummyJUnitFramework.kt index bca9548f..9cc9ddea 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/DummyJUnit5.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/DummyJUnitFramework.kt @@ -10,19 +10,29 @@ import org.junit.runner.notification.RunNotifier import java.lang.reflect.Method /** - * Fake Runner that marks all JUnit 5 methods as ignored, - * used for old devices without Java 8 capabilities. + * Fake Runner that marks all JUnit Framework methods as ignored, + * used for old devices without Java 17 capabilities. */ -internal class DummyJUnit5(private val testClass: Class<*>) : Runner() { +internal class DummyJUnitFramework(private val testClass: Class<*>) : Runner() { private val testMethods: Set = JupiterTestMethodFinder.find(testClass) override fun run(notifier: RunNotifier) { Log.w( LOG_TAG, - "JUnit 5 is not supported on this device: " + - "API level ${Build.VERSION.SDK_INT} is less than 26, the minimum requirement. " + - "All Jupiter tests for ${testClass.name} will be disabled." + buildString { + append("JUnit Framework is not supported on this device: ") + append("API level ${Build.VERSION.SDK_INT} is less than 35, ") + append("the minimum requirement. ") + append("All Jupiter tests for ${testClass.name} will be disabled.") + + // Add a potential recourse for API levels >= 26, but <= 35 + if (Build.VERSION.SDK_INT >= 26) { + append(" You could downgrade to a previous version of the JUnit Framework ") + append("(1.14.0.0) in order to use instrumentation tests for this device, ") + append("as it meets the minimum API level requirement of that version.") + } + } ) for (testMethod in testMethods) { diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/JUnit5RunnerFactory.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/JUnit5RunnerFactory.kt index 4e63c672..23ee764f 100644 --- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/JUnit5RunnerFactory.kt +++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/runners/JUnit5RunnerFactory.kt @@ -6,25 +6,25 @@ import org.junit.runner.Runner /** * Since we can't reference AndroidJUnit5 directly, use this factory for instantiation. * - * On API 26 and above, delegate to the real implementation to drive JUnit 5 tests. + * On API 35 and above, delegate to the real implementation to drive JUnit Framework tests. * Below that however, they wouldn't work; for this case, delegate a dummy runner * which will highlight these tests as ignored. */ -internal fun tryCreateJUnit5Runner( +internal fun tryCreateJUnitFrameworkRunner( klass: Class<*>, paramsSupplier: () -> AndroidJUnit5RunnerParams ): Runner? { - val runner = if (Build.VERSION.SDK_INT >= 26) { - AndroidJUnit5(klass, paramsSupplier) + val runner = if (Build.VERSION.SDK_INT >= 35) { + AndroidJUnitFramework(klass, paramsSupplier) } else { - DummyJUnit5(klass) + DummyJUnitFramework(klass) } // It's still possible for the runner to not be relevant to the test run, // which is related to how further filters are applied (e.g. via @Tag). // Only return the runner to the instrumentation if it has any tests to contribute, // otherwise there would be a mismatch between the number of test classes reported - // to Android, and the number of test classes actually tested with JUnit 5 (ref #298) + // to Android, and the number of test classes actually tested with JUnit Framework (ref #298) return runner.takeIf(Runner::hasExecutableTests) } diff --git a/instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/dummy/JupiterTestMethodFinderTests.kt b/instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/dummy/JupiterTestMethodFinderTests.kt index 3207e8b6..1d144530 100644 --- a/instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/dummy/JupiterTestMethodFinderTests.kt +++ b/instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/dummy/JupiterTestMethodFinderTests.kt @@ -16,7 +16,7 @@ import de.mannodermaus.junit5.HasTaggedTest import de.mannodermaus.junit5.HasTest import de.mannodermaus.junit5.HasTestFactory import de.mannodermaus.junit5.HasTestTemplate -import de.mannodermaus.junit5.internal.runners.AndroidJUnit5 +import de.mannodermaus.junit5.internal.runners.AndroidJUnitFramework import de.mannodermaus.junit5.internal.runners.AndroidJUnit5RunnerParams import org.junit.jupiter.api.DynamicContainer.dynamicContainer import org.junit.jupiter.api.DynamicNode @@ -100,7 +100,7 @@ class JupiterTestMethodFinderTests { notifier.addListener(listener) val params = AndroidJUnit5RunnerParams(filters = listOfNotNull(filter)) - AndroidJUnit5(cls) { params }.run(notifier) + AndroidJUnitFramework(cls) { params }.run(notifier) return listener } diff --git a/instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5Tests.kt b/instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5Tests.kt index 3ce19bac..1210ccd4 100644 --- a/instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5Tests.kt +++ b/instrumentation/runner/src/test/kotlin/de/mannodermaus/junit5/internal/runners/AndroidJUnit5Tests.kt @@ -80,7 +80,7 @@ class AndroidJUnit5Tests { val resultRef = AtomicReference() val args = buildArgs(shardingConfig) withMockedInstrumentation(args) { - val runner = AndroidJUnit5(Sample_NormalTests::class.java) + val runner = AndroidJUnitFramework(Sample_NormalTests::class.java) val listener = CollectingRunListener() val notifier = RunNotifier().also { it.addListener(listener) } runner.run(notifier) diff --git a/instrumentation/sample/build.gradle.kts b/instrumentation/sample/build.gradle.kts index f66e5ff7..03c9bf3a 100644 --- a/instrumentation/sample/build.gradle.kts +++ b/instrumentation/sample/build.gradle.kts @@ -1,4 +1,5 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent +import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { id("com.android.application") @@ -7,7 +8,13 @@ plugins { id("de.mannodermaus.android-junit5").version(Artifacts.Plugin.latestStableVersion) } -val javaVersion = JavaVersion.VERSION_11 +val javaVersion = JavaVersion.VERSION_17 + +kotlin { + compilerOptions { + jvmTarget = JvmTarget.fromTarget(javaVersion.toString()) + } +} android { namespace = "de.mannodermaus.junit5.sample" @@ -48,10 +55,6 @@ android { sourceCompatibility = javaVersion targetCompatibility = javaVersion } - - kotlinOptions { - jvmTarget = javaVersion.toString() - } } junitPlatform { diff --git a/instrumentation/testutil/build.gradle.kts b/instrumentation/testutil/build.gradle.kts index d2172ada..3f050b61 100644 --- a/instrumentation/testutil/build.gradle.kts +++ b/instrumentation/testutil/build.gradle.kts @@ -8,7 +8,7 @@ plugins { kotlin("android") } -val javaVersion = JavaVersion.VERSION_11 +val javaVersion = JavaVersion.VERSION_17 android { namespace = "de.mannodermaus.junit5.testutil" @@ -71,5 +71,6 @@ dependencies { api(libs.mockitoKotlin) api(libs.junitJupiterApi) api(libs.junitJupiterParams) - api(libs.junitPlatformRunner) + api(libs.junitPlatformLauncher) + api(libs.junitPlatformSuiteApi) } From bdf89ce5193654e26bad479781f16c7064fd3b89 Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Tue, 30 Sep 2025 21:13:47 +0900 Subject: [PATCH 3/8] Update Firebase Test Lab devices --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index fbcd6d03..07b4dd6e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ defaults: &defaults working_directory: ~/root/project resource_class: large docker: - - image: cimg/android:2023.04.1 + - image: cimg/android:2025.09.1 environment: GRADLE_OPTS: -Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dorg.gradle.daemon=false -Dorg.gradle.caching=true -Dorg.gradle.configureondemand=true -Dkotlin.compiler.execution.strategy=in-process -Dkotlin.incremental=false @@ -68,8 +68,8 @@ jobs: --test instrumentation/core/build/outputs/apk/androidTest/debug/core-debug-androidTest.apk \ --environment-variables runnerBuilder=de.mannodermaus.junit5.AndroidJUnit5Builder \ --test-runner-class androidx.test.runner.AndroidJUnitRunner \ - --device model=redfin,version=30,locale=en_US,orientation=portrait \ - --device model=oriole,version=33,locale=en_US,orientation=portrait \ + --device model=pa3q,version=35,locale=en_US,orientation=portrait \ + --device model=tokay,version=36,locale=en_US,orientation=portrait \ --results-bucket cloud-test-${GOOGLE_PROJECT_ID} \ --timeout 15m - run: From 37260992baa733a37065dbd02af9365f5e9e3282 Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Tue, 30 Sep 2025 21:14:44 +0900 Subject: [PATCH 4/8] Snapshot version update --- build-logic/src/main/kotlin/Environment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-logic/src/main/kotlin/Environment.kt b/build-logic/src/main/kotlin/Environment.kt index c907df35..e05b9f14 100644 --- a/build-logic/src/main/kotlin/Environment.kt +++ b/build-logic/src/main/kotlin/Environment.kt @@ -93,7 +93,7 @@ object Artifacts { platform = Java, groupId = "de.mannodermaus.gradle.plugins", artifactId = "android-junit5", - currentVersion = "1.14.0.0-SNAPSHOT", + currentVersion = "6.0.0.0-SNAPSHOT", latestStableVersion = "1.13.4.0", description = "Unit Testing with JUnit 5 for Android." ) @@ -103,7 +103,7 @@ object Artifacts { */ object Instrumentation { const val groupId = "de.mannodermaus.junit5" - private const val currentVersion = "1.8.1-SNAPSHOT" + private const val currentVersion = "2.0.0-SNAPSHOT" private const val latestStableVersion = "1.8.0" val Core = Deployed( From ede71102e0607791971643e3b369643d42a620ee Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Tue, 30 Sep 2025 21:21:15 +0900 Subject: [PATCH 5/8] Update readme for testing --- README.md | 54 +++++++++++++++++++++++----------------------- README.md.template | 34 ++++++++++++++--------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 39d0f2a5..fb9092cf 100644 --- a/README.md +++ b/README.md @@ -3,15 +3,15 @@ To update the content of this README, please apply modifications to `README.md.template` instead, and run the `generateReadme` task from Gradle. --> -# android-junit5 [![CircleCI](https://circleci.com/gh/mannodermaus/android-junit5/tree/main.svg?style=svg)][circleci] +# JUnit Jupiter for Android [![CircleCI](https://circleci.com/gh/mannodermaus/android-junit5/tree/main.svg?style=svg)][circleci] -A Gradle plugin that allows for the execution of [JUnit 5][junit5gh] tests in Android environments using **Android Gradle Plugin 8.2 or later.** +A Gradle plugin that allows for the execution of [JUnit Jupiter][junitgh] tests in Android environments using **Android Gradle Plugin 8.2 or later.** ## How? -This plugin configures the unit test tasks for each build variant of a project to run on the JUnit Platform. Furthermore, it provides additional configuration options for these tests [through a DSL][wiki-dsl] and facilitates the usage of JUnit 5 for instrumentation tests. +This plugin configures the unit test tasks for each build variant of a project to run on the JUnit Platform. Furthermore, it provides additional configuration options for these tests [through a DSL][wiki-dsl] and facilitates the usage of JUnit Jupiter for instrumentation tests. -Instructions on how to write tests with the JUnit 5 framework can be found [in their User Guide][junit5ug]. To get a first look at its features, a small showcase project can be found [here][sampletests]. +Instructions on how to write tests with the JUnit framework can be found [in their User Guide][junitug]. To get a first look at its features, a small showcase project can be found [here][sampletests]. ## Setup @@ -27,15 +27,15 @@ To get started, declare the plugin in your `app` module's build script alongside dependencies { // (Required) Writing and executing Unit Tests on the JUnit Platform - testImplementation("org.junit.jupiter:junit-jupiter-api:5.13.4") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.13.4") + testImplementation("org.junit.jupiter:junit-jupiter-api:6.0.0") + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:6.0.0") // (Optional) If you need "Parameterized Tests" - testImplementation("org.junit.jupiter:junit-jupiter-params:5.13.4") + testImplementation("org.junit.jupiter:junit-jupiter-params:6.0.0") // (Optional) If you also have JUnit 4-based tests testImplementation("junit:junit:4.13.2") - testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.13.4") + testRuntimeOnly("org.junit.vintage:junit-vintage-engine:6.0.0") } ``` @@ -50,15 +50,15 @@ To get started, declare the plugin in your `app` module's build script alongside dependencies { // (Required) Writing and executing Unit Tests on the JUnit Platform - testImplementation "org.junit.jupiter:junit-jupiter-api:5.13.4" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.13.4" + testImplementation "org.junit.jupiter:junit-jupiter-api:6.0.0" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:6.0.0" // (Optional) If you need "Parameterized Tests" - testImplementation "org.junit.jupiter:junit-jupiter-params:5.13.4" + testImplementation "org.junit.jupiter:junit-jupiter-params:6.0.0" // (Optional) If you also have JUnit 4-based tests testImplementation "junit:junit:4.13.2" - testRuntimeOnly "org.junit.vintage:junit-vintage-engine:5.13.4" + testRuntimeOnly "org.junit.vintage:junit-vintage-engine:6.0.0" } ``` @@ -115,16 +115,16 @@ The latest version of this plugin requires: ## Instrumentation Test Support -You can use JUnit 5 to run instrumentation tests on emulators and physical devices, too. Because the framework is built on Java 8 from the ground up, these instrumentation tests will only run on devices running Android 8.0 (API 26) or newer – older phones will skip the execution of these tests completely, marking them as "ignored". +You can use JUnit Jupiter to run instrumentation tests on emulators and physical devices, too. Because the framework is built on Java 8 from the ground up, these instrumentation tests will only run on devices running Android 8.0 (API 26) or newer – older phones will skip the execution of these tests completely, marking them as "ignored". -Before you can write instrumentation tests with JUnit Jupiter, make sure that your module is using the `androidx.test.runner.AndroidJUnitRunner` (or a subclass of it) as its `testInstrumentationRunner`. Then, simply add a dependency on `junit-jupiter-api` to the `androidTestImplementation` configuration in your build script and the plugin will automatically configure JUnit 5 tests for you: +Before you can write instrumentation tests with JUnit Jupiter, make sure that your module is using the `androidx.test.runner.AndroidJUnitRunner` (or a subclass of it) as its `testInstrumentationRunner`. Then, simply add a dependency on `junit-jupiter-api` to the `androidTestImplementation` configuration in your build script and the plugin will automatically configure JUnit Jupiter tests for you:
Kotlin ```kotlin dependencies { - androidTestImplementation("org.junit.jupiter:junit-jupiter-api:5.13.4") + androidTestImplementation("org.junit.jupiter:junit-jupiter-api:6.0.0") } ```
@@ -134,12 +134,12 @@ Before you can write instrumentation tests with JUnit Jupiter, make sure that yo ```groovy dependencies { - androidTestImplementation "org.junit.jupiter:junit-jupiter-api:5.13.4" + androidTestImplementation "org.junit.jupiter:junit-jupiter-api:6.0.0" } ``` -By enabling JUnit 5 for instrumentation tests, you will gain access to `ActivityScenarioExtension` (among other things), which helps with the orchestration of `Activity` classes. Check [the wiki][wiki-home] for more info. +By enabling JUnit Jupiter for instrumentation tests, you will gain access to `ActivityScenarioExtension` (among other things), which helps with the orchestration of `Activity` classes. Check [the wiki][wiki-home] for more info. ### Extensions @@ -172,9 +172,9 @@ Can you think of more? Let's discuss in the issues section! ### Jetpack Compose -To test `@Composable` functions on device with JUnit 5, first enable support for instrumentation tests as described above. +To test `@Composable` functions on device with JUnit Jupiter, first enable support for instrumentation tests as described above. Then, add the Compose test dependency to your `androidTestImplementation` configuration -and the plugin will autoconfigure JUnit 5 Compose support for you! +and the plugin will autoconfigure JUnit Jupiter Compose support for you!
Kotlin @@ -204,7 +204,7 @@ and the plugin will autoconfigure JUnit 5 Compose support for you! ```
-[The wiki][wiki-home] includes a section on how to test your Composables with JUnit 5. +[The wiki][wiki-home] includes a section on how to test your Composables with JUnit Jupiter. ### Override the version of instrumentation test libraries @@ -233,7 +233,7 @@ when it sets up the artifacts automatically. However, it is possible to choose a ## Official Support -At this time, Google hasn't shared any immediate plans to bring first-party support for JUnit 5 to Android. The following list is an aggregation of pending feature requests: +At this time, Google hasn't shared any immediate plans to bring first-party support for JUnit Jupiter to Android. The following list is an aggregation of pending feature requests: - [InstantTaskExecutorRule uses @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -- why? (issuetracker.google.com)](https://issuetracker.google.com/u/0/issues/79189568) - [Add support for JUnit 5 (issuetracker.google.com)](https://issuetracker.google.com/issues/127100532) @@ -241,11 +241,11 @@ At this time, Google hasn't shared any immediate plans to bring first-party supp ## Support for @Rules -Since JUnit 5 has replaced the `@Rule` mechanism with Extensions, the following artifacts help bridge the gap until Android officially transitions to JUnit 5. +Since JUnit Jupiter has replaced the `@Rule` mechanism with Extensions, the following artifacts help bridge the gap until Android officially transitions to JUnit Jupiter. ### InstantExecutorExtension -Replaces `InstantTaskExecutorRule` in JUnit 5. +Replaces `InstantTaskExecutorRule` in JUnit Jupiter.
Kotlin @@ -274,7 +274,7 @@ For more details see [instant-task-executor-extension](https://github.com/nebosk This repository contains multiple modules, divided into two sub-projects. The repository's root directory contains build logic shared across the sub-projects, which in turn use symlinks to connect to the common build scripts in their parent folder. - `instrumentation`: The root folder for Android-based modules, namely the instrumentation libraries & a sample application. After cloning, open this project in Android Studio. -- `plugin`: The root folder for Java-based modules, namely the Gradle plugin for JUnit 5 on Android, as well as its test module. After cloning, open this project in IntelliJ IDEA. +- `plugin`: The root folder for Java-based modules, namely the Gradle plugin for JUnit Jupiter on Android, as well as its test module. After cloning, open this project in IntelliJ IDEA. ## Plugin Compatibility Map @@ -283,7 +283,7 @@ refer to the table below to find a suitable alternative version. Note that **no legacy versions**, so please consider upgrading to at least Android Gradle Plugin 8.2 before filing an issue with the latest one. -|Your AGP Version|Suggested JUnit5 Plugin Version| +|Your AGP Version|Suggested Plugin Version| |---|---| |`>= 8.2.0`|`1.13.4.0`| |`8.0.0` - `8.1.4`|`1.12.2.0`| @@ -312,8 +312,8 @@ limitations under the License. See also the [full License text](LICENSE). - [junit5gh]: https://github.com/junit-team/junit5 - [junit5ug]: https://junit.org/junit5/docs/current/user-guide + [junitgh]: https://github.com/junit-team/junit5 + [junitug]: https://junit.org/junit5/docs/current/user-guide [circleci]: https://circleci.com/gh/mannodermaus/android-junit5 [sonatyperepo]: https://central.sonatype.com/repository/maven-snapshots [sampletests]: instrumentation/sample diff --git a/README.md.template b/README.md.template index 46d1ac7f..53bf8852 100644 --- a/README.md.template +++ b/README.md.template @@ -1,12 +1,12 @@ -# android-junit5 [![CircleCI](https://circleci.com/gh/mannodermaus/android-junit5/tree/main.svg?style=svg)][circleci] +# JUnit Jupiter for Android [![CircleCI](https://circleci.com/gh/mannodermaus/android-junit5/tree/main.svg?style=svg)][circleci] -A Gradle plugin that allows for the execution of [JUnit 5][junit5gh] tests in Android environments using **Android Gradle Plugin ${constants.minimumRequiredAgpVersion} or later.** +A Gradle plugin that allows for the execution of [JUnit Jupiter][junitgh] tests in Android environments using **Android Gradle Plugin ${constants.minimumRequiredAgpVersion} or later.** ## How? -This plugin configures the unit test tasks for each build variant of a project to run on the JUnit Platform. Furthermore, it provides additional configuration options for these tests [through a DSL][wiki-dsl] and facilitates the usage of JUnit 5 for instrumentation tests. +This plugin configures the unit test tasks for each build variant of a project to run on the JUnit Platform. Furthermore, it provides additional configuration options for these tests [through a DSL][wiki-dsl] and facilitates the usage of JUnit Jupiter for instrumentation tests. -Instructions on how to write tests with the JUnit 5 framework can be found [in their User Guide][junit5ug]. To get a first look at its features, a small showcase project can be found [here][sampletests]. +Instructions on how to write tests with the JUnit framework can be found [in their User Guide][junitug]. To get a first look at its features, a small showcase project can be found [here][sampletests]. ## Setup @@ -110,9 +110,9 @@ The latest version of this plugin requires: ## Instrumentation Test Support -You can use JUnit 5 to run instrumentation tests on emulators and physical devices, too. Because the framework is built on Java 8 from the ground up, these instrumentation tests will only run on devices running Android 8.0 (API 26) or newer – older phones will skip the execution of these tests completely, marking them as "ignored". +You can use JUnit Jupiter to run instrumentation tests on emulators and physical devices, too. Because the framework is built on Java 8 from the ground up, these instrumentation tests will only run on devices running Android 8.0 (API 26) or newer – older phones will skip the execution of these tests completely, marking them as "ignored". -Before you can write instrumentation tests with JUnit Jupiter, make sure that your module is using the `androidx.test.runner.AndroidJUnitRunner` (or a subclass of it) as its `testInstrumentationRunner`. Then, simply add a dependency on `junit-jupiter-api` to the `androidTestImplementation` configuration in your build script and the plugin will automatically configure JUnit 5 tests for you: +Before you can write instrumentation tests with JUnit Jupiter, make sure that your module is using the `androidx.test.runner.AndroidJUnitRunner` (or a subclass of it) as its `testInstrumentationRunner`. Then, simply add a dependency on `junit-jupiter-api` to the `androidTestImplementation` configuration in your build script and the plugin will automatically configure JUnit Jupiter tests for you:
Kotlin @@ -134,7 +134,7 @@ Before you can write instrumentation tests with JUnit Jupiter, make sure that yo ```
-By enabling JUnit 5 for instrumentation tests, you will gain access to `ActivityScenarioExtension` (among other things), which helps with the orchestration of `Activity` classes. Check [the wiki][wiki-home] for more info. +By enabling JUnit Jupiter for instrumentation tests, you will gain access to `ActivityScenarioExtension` (among other things), which helps with the orchestration of `Activity` classes. Check [the wiki][wiki-home] for more info. ### Extensions @@ -167,9 +167,9 @@ Can you think of more? Let's discuss in the issues section! ### Jetpack Compose -To test `@Composable` functions on device with JUnit 5, first enable support for instrumentation tests as described above. +To test `@Composable` functions on device with JUnit Jupiter, first enable support for instrumentation tests as described above. Then, add the Compose test dependency to your `androidTestImplementation` configuration -and the plugin will autoconfigure JUnit 5 Compose support for you! +and the plugin will autoconfigure JUnit Jupiter Compose support for you!
Kotlin @@ -199,7 +199,7 @@ and the plugin will autoconfigure JUnit 5 Compose support for you! ```
-[The wiki][wiki-home] includes a section on how to test your Composables with JUnit 5. +[The wiki][wiki-home] includes a section on how to test your Composables with JUnit Jupiter. ### Override the version of instrumentation test libraries @@ -228,7 +228,7 @@ when it sets up the artifacts automatically. However, it is possible to choose a ## Official Support -At this time, Google hasn't shared any immediate plans to bring first-party support for JUnit 5 to Android. The following list is an aggregation of pending feature requests: +At this time, Google hasn't shared any immediate plans to bring first-party support for JUnit Jupiter to Android. The following list is an aggregation of pending feature requests: - [InstantTaskExecutorRule uses @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -- why? (issuetracker.google.com)](https://issuetracker.google.com/u/0/issues/79189568) - [Add support for JUnit 5 (issuetracker.google.com)](https://issuetracker.google.com/issues/127100532) @@ -236,11 +236,11 @@ At this time, Google hasn't shared any immediate plans to bring first-party supp ## Support for @Rules -Since JUnit 5 has replaced the `@Rule` mechanism with Extensions, the following artifacts help bridge the gap until Android officially transitions to JUnit 5. +Since JUnit Jupiter has replaced the `@Rule` mechanism with Extensions, the following artifacts help bridge the gap until Android officially transitions to JUnit Jupiter. ### InstantExecutorExtension -Replaces `InstantTaskExecutorRule` in JUnit 5. +Replaces `InstantTaskExecutorRule` in JUnit Jupiter.
Kotlin @@ -269,7 +269,7 @@ For more details see [instant-task-executor-extension](https://github.com/nebosk This repository contains multiple modules, divided into two sub-projects. The repository's root directory contains build logic shared across the sub-projects, which in turn use symlinks to connect to the common build scripts in their parent folder. - `instrumentation`: The root folder for Android-based modules, namely the instrumentation libraries & a sample application. After cloning, open this project in Android Studio. -- `plugin`: The root folder for Java-based modules, namely the Gradle plugin for JUnit 5 on Android, as well as its test module. After cloning, open this project in IntelliJ IDEA. +- `plugin`: The root folder for Java-based modules, namely the Gradle plugin for JUnit Jupiter on Android, as well as its test module. After cloning, open this project in IntelliJ IDEA. ## Plugin Compatibility Map @@ -278,7 +278,7 @@ refer to the table below to find a suitable alternative version. Note that **no legacy versions**, so please consider upgrading to at least Android Gradle Plugin ${constants.minimumRequiredAgpVersion} before filing an issue with the latest one. -|Your AGP Version|Suggested JUnit5 Plugin Version| +|Your AGP Version|Suggested Plugin Version| |---|---| |`>= 8.2.0`|`${pluginVersion}`| |`8.0.0` - `8.1.4`|`1.12.2.0`| @@ -307,8 +307,8 @@ limitations under the License. See also the [full License text](LICENSE). - [junit5gh]: https://github.com/junit-team/junit5 - [junit5ug]: https://junit.org/junit5/docs/current/user-guide + [junitgh]: https://github.com/junit-team/junit5 + [junitug]: https://junit.org/junit5/docs/current/user-guide [circleci]: https://circleci.com/gh/mannodermaus/android-junit5 [sonatyperepo]: https://central.sonatype.com/repository/maven-snapshots [sampletests]: instrumentation/sample From f4bf8ef45932e455a59e506085feb82353b853df Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Tue, 30 Sep 2025 21:35:12 +0900 Subject: [PATCH 6/8] Tweak test conditions --- .../junit5/condition/DisabledOnSdkVersionIntegrationTests.kt | 4 ++-- .../junit5/condition/EnabledOnSdkVersionIntegrationTests.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionIntegrationTests.kt b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionIntegrationTests.kt index 0796e3e3..b4aad0a2 100644 --- a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionIntegrationTests.kt +++ b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/DisabledOnSdkVersionIntegrationTests.kt @@ -29,13 +29,13 @@ class DisabledOnSdkVersionIntegrationTests { } @Disabled("Used by DisabledOnSdkVersionConditionTests only") - @DisabledOnSdkVersion(from = 24, until = 29) + @DisabledOnSdkVersion(from = 24, until = 35) @Test fun disabledBecauseApiIsInValidRange() { } @Disabled("Used by DisabledOnSdkVersionConditionTests only") - @DisabledOnSdkVersion(from = 27) + @DisabledOnSdkVersion(from = 36) @Test fun enabledBecauseMinApiLowEnough() { } diff --git a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionIntegrationTests.kt b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionIntegrationTests.kt index f777e2a7..65dbd184 100644 --- a/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionIntegrationTests.kt +++ b/instrumentation/core/src/test/java/de/mannodermaus/junit5/condition/EnabledOnSdkVersionIntegrationTests.kt @@ -29,13 +29,13 @@ class EnabledOnSdkVersionIntegrationTests { } @Disabled("Used by EnabledOnSdkVersionConditionTests only") - @EnabledOnSdkVersion(from = 24, until = 29) + @EnabledOnSdkVersion(from = 24, until = 36) @Test fun enabledBecauseApiIsInValidRange() { } @Disabled("Used by EnabledOnSdkVersionConditionTests only") - @EnabledOnSdkVersion(from = 27) + @EnabledOnSdkVersion(from = 36) @Test fun disabledBecauseMinApiTooLow() { } From 4503521764f68ddefb39c82b8be5817b234d2b2c Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Tue, 30 Sep 2025 22:15:15 +0900 Subject: [PATCH 7/8] apiDump --- instrumentation/compose/api/compose.api | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/instrumentation/compose/api/compose.api b/instrumentation/compose/api/compose.api index 227624ab..8f714395 100644 --- a/instrumentation/compose/api/compose.api +++ b/instrumentation/compose/api/compose.api @@ -30,10 +30,16 @@ public abstract interface class de/mannodermaus/junit5/compose/ComposeContext : public abstract fun waitForIdle ()V public abstract fun waitUntil (JLkotlin/jvm/functions/Function0;)V public abstract fun waitUntil (Ljava/lang/String;JLkotlin/jvm/functions/Function0;)V + public static synthetic fun waitUntil$default (Lde/mannodermaus/junit5/compose/ComposeContext;JLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V + public static synthetic fun waitUntil$default (Lde/mannodermaus/junit5/compose/ComposeContext;Ljava/lang/String;JLkotlin/jvm/functions/Function0;ILjava/lang/Object;)V public abstract fun waitUntilAtLeastOneExists (Landroidx/compose/ui/test/SemanticsMatcher;J)V + public static synthetic fun waitUntilAtLeastOneExists$default (Lde/mannodermaus/junit5/compose/ComposeContext;Landroidx/compose/ui/test/SemanticsMatcher;JILjava/lang/Object;)V public abstract fun waitUntilDoesNotExist (Landroidx/compose/ui/test/SemanticsMatcher;J)V + public static synthetic fun waitUntilDoesNotExist$default (Lde/mannodermaus/junit5/compose/ComposeContext;Landroidx/compose/ui/test/SemanticsMatcher;JILjava/lang/Object;)V public abstract fun waitUntilExactlyOneExists (Landroidx/compose/ui/test/SemanticsMatcher;J)V + public static synthetic fun waitUntilExactlyOneExists$default (Lde/mannodermaus/junit5/compose/ComposeContext;Landroidx/compose/ui/test/SemanticsMatcher;JILjava/lang/Object;)V public abstract fun waitUntilNodeCount (Landroidx/compose/ui/test/SemanticsMatcher;IJ)V + public static synthetic fun waitUntilNodeCount$default (Lde/mannodermaus/junit5/compose/ComposeContext;Landroidx/compose/ui/test/SemanticsMatcher;IJILjava/lang/Object;)V } public final class de/mannodermaus/junit5/compose/ComposeContext$DefaultImpls { @@ -46,7 +52,7 @@ public final class de/mannodermaus/junit5/compose/ComposeContext$DefaultImpls { } public abstract interface class de/mannodermaus/junit5/compose/ComposeExtension : org/junit/jupiter/api/extension/Extension { - public abstract fun runComposeTest (Lkotlin/jvm/functions/Function1;)V + public fun runComposeTest (Lkotlin/jvm/functions/Function1;)V public abstract fun use (Lkotlin/jvm/functions/Function1;)V } From 3bbde6c9208ab7c05214d0d2cfe8d6073cb8d4f6 Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Tue, 30 Sep 2025 22:41:41 +0900 Subject: [PATCH 8/8] Only 1 FTL device --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 07b4dd6e..2527ca68 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,7 +69,6 @@ jobs: --environment-variables runnerBuilder=de.mannodermaus.junit5.AndroidJUnit5Builder \ --test-runner-class androidx.test.runner.AndroidJUnitRunner \ --device model=pa3q,version=35,locale=en_US,orientation=portrait \ - --device model=tokay,version=36,locale=en_US,orientation=portrait \ --results-bucket cloud-test-${GOOGLE_PROJECT_ID} \ --timeout 15m - run: