diff --git a/.circleci/config.yml b/.circleci/config.yml
index fbcd6d03..4e0f696d 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,12 +3,12 @@ defaults: &defaults
working_directory: ~/root/project
resource_class: large
docker:
- - image: cimg/android:2023.04.1
+ - image: cimg/android:2025.12.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
cache_key: &cache_key
- key: jars-{{ checksum "build-logic/build.gradle.kts" }}-{{ checksum "plugin/build.gradle.kts" }}-{{ checksum "plugin/android-junit5/build.gradle.kts" }}-{{ checksum "plugin/gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "instrumentation/build.gradle.kts" }}-{{ checksum "instrumentation/core/build.gradle.kts" }}-{{ checksum "instrumentation/compose/build.gradle.kts" }}-{{ checksum "instrumentation/extensions/build.gradle.kts" }}-{{ checksum "instrumentation/runner/build.gradle.kts" }}-{{ checksum "instrumentation/sample/build.gradle.kts" }}-{{ checksum "instrumentation/gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "build-logic/src/main/kotlin/Environment.kt" }}-{{ checksum "build-logic/src/main/kotlin/Dependencies.kt" }}
+ key: jars-{{ checksum "build-logic/build.gradle.kts" }}-{{ checksum "plugin/build.gradle.kts" }}-{{ checksum "plugin/android-junit5/build.gradle.kts" }}-{{ checksum "plugin/gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "instrumentation/build.gradle.kts" }}-{{ checksum "instrumentation/core/build.gradle.kts" }}-{{ checksum "instrumentation/compose/build.gradle.kts" }}-{{ checksum "instrumentation/extensions/build.gradle.kts" }}-{{ checksum "instrumentation/runner/build.gradle.kts" }}-{{ checksum "instrumentation/sample/build.gradle.kts" }}-{{ checksum "instrumentation/gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "build-logic/src/main/kotlin/Environment.kt" }}-{{ checksum "build-logic/gradle/libs.versions.toml" }}
commands:
construct_signing_key:
@@ -35,17 +35,10 @@ jobs:
command: cd instrumentation && ./gradlew androidDependencies
- run:
name: (Instrumentation) Build
- command: |
- cd instrumentation
- ./gradlew assembleRelease :core:assembleDebug \
- :core:assembleDebugAndroidTest \
- :compose:assembleDebugAndroidTest \
- :extensions:assembleDebug \
- :runner:assembleDebug \
- :sample:assembleDebug --stacktrace
+ command: cd instrumentation && ./gradlew assemble :core:assembleAndroidTest --stacktrace
- run:
name: (Instrumentation) Test
- command: cd instrumentation && ./gradlew :core:check :extensions:check :runner:check :compose:check --stacktrace
+ command: cd instrumentation && ./gradlew check --stacktrace
- save_cache:
<<: *cache_key
paths:
@@ -60,18 +53,30 @@ jobs:
sudo gcloud auth activate-service-account --key-file=${HOME}/gcloud-service-key.json
sudo gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
- run:
- name: Test with Firebase Test Lab
+ name: Test with Firebase Test Lab (JUnit 5)
command: >
sudo gcloud firebase test android run \
--type instrumentation \
- --app instrumentation/sample/build/outputs/apk/debug/sample-debug.apk \
- --test instrumentation/core/build/outputs/apk/androidTest/debug/core-debug-androidTest.apk \
- --environment-variables runnerBuilder=de.mannodermaus.junit5.AndroidJUnit5Builder \
+ --app instrumentation/sample/build/outputs/apk/five/debug/sample-five-debug.apk \
+ --test instrumentation/core/build/outputs/apk/androidTest/five/debug/core-five-debug-androidTest.apk \
+ --environment-variables runnerBuilder=de.mannodermaus.junit5.AndroidJUnitFrameworkBuilder \
--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 \
--results-bucket cloud-test-${GOOGLE_PROJECT_ID} \
--timeout 15m
+ - run:
+ name: Test with Firebase Test Lab (JUnit 6)
+ command: >
+ sudo gcloud firebase test android run \
+ --type instrumentation \
+ --app instrumentation/sample/build/outputs/apk/six/debug/sample-six-debug.apk \
+ --test instrumentation/core/build/outputs/apk/androidTest/six/debug/core-six-debug-androidTest.apk \
+ --environment-variables runnerBuilder=de.mannodermaus.junit5.AndroidJUnitFrameworkBuilder \
+ --test-runner-class androidx.test.runner.AndroidJUnitRunner \
+ --device model=pa3q,version=35,locale=en_US,orientation=portrait \
+ --results-bucket cloud-test-${GOOGLE_PROJECT_ID} \
+ --timeout 15m
- run:
name: Install gsutil dependency and copy test results data
command: |
@@ -112,12 +117,12 @@ jobs:
name: (Instrumentation) Build & Deploy
command: |
cd instrumentation
- ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository --stacktrace
+ ./gradlew publishAllPublicationsToSonatypeRepository closeAndReleaseStagingRepositories --stacktrace
- run:
name: (Plugin) Build & Deploy
command: |
cd plugin
- ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository --stacktrace
+ ./gradlew publishAllPublicationsToSonatypeRepository closeAndReleaseStagingRepositories --stacktrace
- store_artifacts:
path: plugin/android-junit5/build/publications
destination: plugin/publications/snapshots
diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml
index 3deb449c..64118725 100644
--- a/.github/workflows/gradle-wrapper-validation.yml
+++ b/.github/workflows/gradle-wrapper-validation.yml
@@ -8,5 +8,5 @@ jobs:
name: "Validation"
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: gradle/actions/wrapper-validation@v4
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
+ - uses: gradle/actions/wrapper-validation@bfd569614358980afc8f89c2730eee75bb97efdf # v5
diff --git a/.images/logo-inverted.svg b/.images/logo-inverted.svg
new file mode 100644
index 00000000..0507192a
--- /dev/null
+++ b/.images/logo-inverted.svg
@@ -0,0 +1,47 @@
+
+
+
diff --git a/.images/logo.af b/.images/logo.af
new file mode 100644
index 00000000..fa8b1bf5
Binary files /dev/null and b/.images/logo.af differ
diff --git a/.images/logo.png b/.images/logo.png
deleted file mode 100644
index 1940fc21..00000000
Binary files a/.images/logo.png and /dev/null differ
diff --git a/.images/logo.psd b/.images/logo.psd
deleted file mode 100644
index abf3b98a..00000000
Binary files a/.images/logo.psd and /dev/null differ
diff --git a/.images/logo.svg b/.images/logo.svg
new file mode 100644
index 00000000..b01aa2a8
--- /dev/null
+++ b/.images/logo.svg
@@ -0,0 +1,47 @@
+
+
+
diff --git a/README.md b/README.md
index f8640716..15e2e670 100644
--- a/README.md
+++ b/README.md
@@ -3,237 +3,131 @@
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]
+
android-junit5 [][circleci]
+When applied to a test class it attempts to grant all requested runtime permissions.
* The requested permissions will then be granted on the device and will take immediate effect.
- * Permissions can only be requested on Android M (API 23) or above and will be ignored on all other
- * API levels. Once a permission is granted it will apply for all tests running in the current
- * Instrumentation. There is no way of revoking a permission after it was granted. Attempting to do
- * so will crash the Instrumentation process.
+ * Once a permission is granted it will apply for all tests running in the current Instrumentation.
+ * There is no way of revoking a permission after it was granted.
+ * Attempting to do so will crash the Instrumentation process.
*/
@SuppressLint("RestrictedApi")
public class GrantPermissionExtension
@@ -37,7 +36,6 @@ internal constructor(private val permissionGranter: PermissionGranter) : BeforeE
*
* @see android.Manifest.permission
*/
- @ExperimentalTestApi
@JvmStatic
public fun grant(vararg permissions: String): GrantPermissionExtension {
val granter = loadSingleService(PermissionGranter::class.java, ::PermissionRequester)
@@ -51,7 +49,7 @@ internal constructor(private val permissionGranter: PermissionGranter) : BeforeE
val set = LinkedHashSet
+ * android {
+ * defaultConfig {
+ * testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ * testInstrumentationRunnerArgument("runnerBuilder", "de.mannodermaus.junit5.AndroidJUnitFrameworkBuilder")
+ * }
+ * }
+ *
+ *
+ * (Suppressing unused, since this is hooked into the
+ * project configuration via a Test Instrumentation Runner Argument.)
+ */
+@Deprecated(
+ message = "Renamed to AndroidJUnitFrameworkBuilder",
+ replaceWith = ReplaceWith("AndroidJUnitFrameworkBuilder")
+)
+public class AndroidJUnit5Builder : AndroidJUnitFrameworkBuilder()
diff --git a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/RunnerInternalConstants.kt b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/RunnerInternalConstants.kt
index 4eb0f23f..dbb1e3d1 100644
--- a/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/RunnerInternalConstants.kt
+++ b/instrumentation/runner/src/main/kotlin/de/mannodermaus/junit5/internal/RunnerInternalConstants.kt
@@ -1,3 +1,3 @@
package de.mannodermaus.junit5.internal
-internal const val LOG_TAG = "AndroidJUnit5"
+internal const val LOG_TAG = "AndroidJUnitFramework"
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 904cb4f6..f3d44c2d 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
@@ -1,38 +1,26 @@
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.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)
internal object EmptyTestPlan : TestPlan(
- false,
- emptyConfigurationParameters,
- emptyOutputDirectoryCreator
+ /* containsTests = */ false,
+ /* configurationParameters = */ EmptyConfigurationParameters,
+ /* outputDirectoryCreator = */ emptyOutputDirectoryCreator
)
-@RequiresApi(26)
-private val emptyConfigurationParameters = object : ConfigurationParameters {
- override fun get(key: String?) = Optional.empty