diff --git a/.circleci/config.yml b/.circleci/config.yml
index fbcd6d03..2527ca68 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,7 @@ 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 \
--results-bucket cloud-test-${GOOGLE_PROJECT_ID} \
--timeout 15m
- run:
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]
+#
JUnit Jupiter for Android [][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]
+#
JUnit Jupiter for Android [][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
diff --git a/build-logic/src/main/kotlin/Dependencies.kt b/build-logic/src/main/kotlin/Dependencies.kt
index 5afae149..c826f50c 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 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/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(
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/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/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
}
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..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
@@ -23,19 +23,19 @@ class DisabledOnSdkVersionIntegrationTests {
}
@Disabled("Used by DisabledOnSdkVersionConditionTests only")
- @DisabledOnSdkVersion(until = 26)
+ @DisabledOnSdkVersion(until = 35)
@Test
fun disabledBecauseMaxApiIsMatched() {
}
@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/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..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
@@ -23,19 +23,19 @@ class EnabledOnSdkVersionIntegrationTests {
}
@Disabled("Used by EnabledOnSdkVersionConditionTests only")
- @EnabledOnSdkVersion(until = 26)
+ @EnabledOnSdkVersion(until = 35)
@Test
fun enabledBecauseMaxApiIsMatched() {
}
@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() {
}
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)
}
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))
}