diff --git a/.images/logo.psd b/.images/logo.psd
index 83a431ec..abf3b98a 100644
Binary files a/.images/logo.psd and b/.images/logo.psd differ
diff --git a/README.md b/README.md
index 989ef5b4..72528f66 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ Furthermore, this repository provides a small showcase of the functionality prov
```groovy
buildscript {
dependencies {
- classpath "de.mannodermaus.gradle.plugins:android-junit5:1.5.1.0"
+ classpath "de.mannodermaus.gradle.plugins:android-junit5:1.5.2.0"
}
}
```
@@ -31,7 +31,7 @@ Furthermore, this repository provides a small showcase of the functionality prov
```kotlin
buildscript {
dependencies {
- classpath("de.mannodermaus.gradle.plugins:android-junit5:1.5.1.0")
+ classpath("de.mannodermaus.gradle.plugins:android-junit5:1.5.2.0")
}
}
```
@@ -51,15 +51,15 @@ Snapshots of the development version are available through [Sonatype's `snapshot
dependencies {
// (Required) Writing and executing Unit Tests on the JUnit Platform
- testImplementation "org.junit.jupiter:junit-jupiter-api:5.5.1"
- testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.5.1"
+ testImplementation "org.junit.jupiter:junit-jupiter-api:5.5.2"
+ testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.5.2"
// (Optional) If you need "Parameterized Tests"
- testImplementation "org.junit.jupiter:junit-jupiter-params:5.5.1"
+ testImplementation "org.junit.jupiter:junit-jupiter-params:5.5.2"
// (Optional) If you also have JUnit 4-based tests
testImplementation "junit:junit:4.12"
- testRuntimeOnly "org.junit.vintage:junit-vintage-engine:5.5.1"
+ testRuntimeOnly "org.junit.vintage:junit-vintage-engine:5.5.2"
}
```
@@ -74,15 +74,15 @@ Snapshots of the development version are available through [Sonatype's `snapshot
dependencies {
// (Required) Writing and executing Unit Tests on the JUnit Platform
- testImplementation("org.junit.jupiter:junit-jupiter-api:5.5.1")
- testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.5.1")
+ testImplementation("org.junit.jupiter:junit-jupiter-api:5.5.2")
+ testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.5.2")
// (Optional) If you need "Parameterized Tests"
- testImplementation("org.junit.jupiter:junit-jupiter-params:5.5.1")
+ testImplementation("org.junit.jupiter:junit-jupiter-params:5.5.2")
// (Optional) If you also have JUnit 4-based tests
testImplementation("junit:junit:4.12")
- testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.5.1")
+ testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.5.2")
}
```
@@ -129,8 +129,8 @@ To start writing instrumentation tests with JUnit Jupiter, make the following ch
dependencies {
// 5) Jupiter API & Test Runner, if you don't have it already
- androidTestImplementation "androidx.test:runner:1.1.1"
- androidTestImplementation "org.junit.jupiter:junit-jupiter-api:5.5.1"
+ androidTestImplementation "androidx.test:runner:1.2.0"
+ androidTestImplementation "org.junit.jupiter:junit-jupiter-api:5.5.2"
// 6) The instrumentation test companion libraries
androidTestImplementation "de.mannodermaus.junit5:android-test-core:1.1.0"
@@ -164,8 +164,8 @@ To start writing instrumentation tests with JUnit Jupiter, make the following ch
}
dependencies {
// 5) Jupiter API & Test Runner, if you don't have it already
- androidTestImplementation("androidx.test:runner:1.1.1")
- androidTestImplementation("org.junit.jupiter:junit-jupiter-api:5.5.1")
+ androidTestImplementation("androidx.test:runner:1.2.0")
+ androidTestImplementation("org.junit.jupiter:junit-jupiter-api:5.5.2")
// 6) The instrumentation test companion libraries
androidTestImplementation("de.mannodermaus.junit5:android-test-core:1.1.0")
diff --git a/README.md.template b/README.md.template
new file mode 100644
index 00000000..38e4c409
--- /dev/null
+++ b/README.md.template
@@ -0,0 +1,220 @@
+# android-junit5 [][circleci]
+
+
+
+A Gradle plugin that allows for the execution of [JUnit 5][junit5gh] tests in Android environments using **Android Gradle Plugin 3.2.0 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] attached to `android.testOptions`.
+
+Instructions on how to write JUnit 5 tests can be found [in their User Guide][junit5ug].
+Furthermore, this repository provides a small showcase of the functionality provided by JUnit 5 [here][sampletests].
+
+## Download
+
+
+ Groovy
+
+ ```groovy
+ buildscript {
+ dependencies {
+ classpath "de.mannodermaus.gradle.plugins:android-junit5:${pluginVersion}"
+ }
+ }
+ ```
+
+
+
+ Kotlin
+
+ ```kotlin
+ buildscript {
+ dependencies {
+ classpath("de.mannodermaus.gradle.plugins:android-junit5:${pluginVersion}")
+ }
+ }
+ ```
+
+
+
+
+Snapshots of the development version are available through [Sonatype's `snapshots` repository][sonatyperepo].
+
+## Setup
+
+
+ Groovy
+
+ ```groovy
+ apply plugin: "de.mannodermaus.android-junit5"
+
+ dependencies {
+ // (Required) Writing and executing Unit Tests on the JUnit Platform
+ testImplementation "org.junit.jupiter:junit-jupiter-api:${Versions.org_junit_jupiter}"
+ testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${Versions.org_junit_jupiter}"
+
+ // (Optional) If you need "Parameterized Tests"
+ testImplementation "org.junit.jupiter:junit-jupiter-params:${Versions.org_junit_jupiter}"
+
+ // (Optional) If you also have JUnit 4-based tests
+ testImplementation "junit:junit:${Versions.junit}"
+ testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${Versions.junit_vintage_engine}"
+ }
+ ```
+
+
+
+ Kotlin
+
+ ```kotlin
+ plugins {
+ id("de.mannodermaus.android-junit5")
+ }
+
+ dependencies {
+ // (Required) Writing and executing Unit Tests on the JUnit Platform
+ testImplementation("org.junit.jupiter:junit-jupiter-api:${Versions.org_junit_jupiter}")
+ testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${Versions.org_junit_jupiter}")
+
+ // (Optional) If you need "Parameterized Tests"
+ testImplementation("org.junit.jupiter:junit-jupiter-params:${Versions.org_junit_jupiter}")
+
+ // (Optional) If you also have JUnit 4-based tests
+ testImplementation("junit:junit:${Versions.junit}")
+ testRuntimeOnly("org.junit.vintage:junit-vintage-engine:${Versions.junit_vintage_engine}")
+ }
+ ```
+
+
+
+
+More information on Getting Started can be found [on the wiki][wiki-gettingstarted].
+
+## Requirements
+
+The latest version of this plugin requires:
+* Android Gradle Plugin `3.2.0` or above
+* Gradle `4.7` or above
+
+## Instrumentation Test Support
+
+There is experimental support for Android instrumentation tests, which requires some additional configuration & dependencies. Furthermore, because JUnit 5 is built on Java 8 from the ground up, its 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".
+
+To start writing instrumentation tests with JUnit Jupiter, make the following changes to your module's build script:
+
+
+ Groovy
+
+ ```groovy
+ android {
+ defaultConfig {
+ // 1) Make sure to use the AndroidJUnitRunner, of a subclass of it. This requires a dependency on androidx.test:runner, too!
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ // 2) Connect JUnit 5 to the runner
+ testInstrumentationRunnerArgument "runnerBuilder", "de.mannodermaus.junit5.AndroidJUnit5Builder"
+ }
+
+ // 3) Java 8 is required
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ // 4) JUnit 5 will bundle in files with identical paths; exclude them
+ packagingOptions {
+ exclude "META-INF/LICENSE*"
+ }
+ }
+
+ dependencies {
+ // 5) Jupiter API & Test Runner, if you don't have it already
+ androidTestImplementation "androidx.test:runner:${Versions.androidx_test_runner}"
+ androidTestImplementation "org.junit.jupiter:junit-jupiter-api:${Versions.org_junit_jupiter}"
+
+ // 6) The instrumentation test companion libraries
+ androidTestImplementation "de.mannodermaus.junit5:android-test-core:${instrumentationVersion}"
+ androidTestRuntimeOnly "de.mannodermaus.junit5:android-test-runner:${instrumentationVersion}"
+ }
+ ```
+
+
+
+ Kotlin
+
+ ```groovy
+ android {
+ defaultConfig {
+ // 1) Make sure to use the AndroidJUnitRunner, of a subclass of it. This requires a dependency on androidx.test:runner, too!
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ // 2) Connect JUnit 5 to the runner
+ testInstrumentationRunnerArgument("runnerBuilder", "de.mannodermaus.junit5.AndroidJUnit5Builder")
+ }
+
+ // 3) Java 8 is required
+ compileOptions {
+ setSourceCompatibility(JavaVersion.VERSION_1_8)
+ setTargetCompatibility(JavaVersion.VERSION_1_8)
+ }
+
+ // 4) JUnit 5 will bundle in files with identical paths; exclude them
+ packagingOptions {
+ exclude("META-INF/LICENSE*")
+ }
+ }
+ dependencies {
+ // 5) Jupiter API & Test Runner, if you don't have it already
+ androidTestImplementation("androidx.test:runner:${Versions.androidx_test_runner}")
+ androidTestImplementation("org.junit.jupiter:junit-jupiter-api:${Versions.org_junit_jupiter}")
+
+ // 6) The instrumentation test companion libraries
+ androidTestImplementation("de.mannodermaus.junit5:android-test-core:${instrumentationVersion}")
+ androidTestRuntimeOnly("de.mannodermaus.junit5:android-test-runner:${instrumentationVersion}")
+ }
+ ```
+
+
+The `android-test-core` artifact includes an extension point for the `ActivityScenario` API; more information on that can be found in the wiki.
+
+# 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:
+
+- [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)
+- [JUnit 5 support (github.com/android/android-test)](https://github.com/android/android-test/issues/224)
+
+# Building Locally
+
+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.
+
+## License
+
+```
+Copyright 2017-2019 Marcel Schnelle
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+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
+ [circleci]: https://circleci.com/gh/mannodermaus/android-junit5
+ [sonatyperepo]: https://oss.sonatype.org/content/repositories/snapshots
+ [sampletests]: instrumentation/sample
+ [wiki-dsl]: https://github.com/mannodermaus/android-junit5/wiki/Configuration-DSL
+ [wiki-gettingstarted]: https://github.com/mannodermaus/android-junit5/wiki/Getting-Started
diff --git a/build.gradle.kts b/build.gradle.kts
index 252fb193..a37bd6dd 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -32,3 +32,21 @@ allprojects {
// Store deployment credentials (used in deployment.gradle)
extra["deployCredentials"] = DeployCredentials(project)
}
+
+tasks.create("generateReadme") {
+ // Find folder containing README.md
+ // (required because this script file is included through symlinks in sub-projects)
+ var rootFolder = project.rootDir
+ while (rootFolder != null && rootFolder.exists()) {
+ val inFile = File(rootFolder, "README.md.template")
+ val outFile = File(rootFolder, "README.md")
+
+ if (inFile.exists() && outFile.exists()) {
+ this.inputTemplateFile = inFile
+ this.outputFile = outFile
+ break
+ }
+
+ rootFolder = rootFolder.parentFile
+ }
+}
diff --git a/buildSrc/src/main/kotlin/Artifacts.kt b/buildSrc/src/main/kotlin/Artifacts.kt
index c9d5af2c..16097968 100644
--- a/buildSrc/src/main/kotlin/Artifacts.kt
+++ b/buildSrc/src/main/kotlin/Artifacts.kt
@@ -35,8 +35,8 @@ object Artifacts {
platform = Java,
groupId = "de.mannodermaus.gradle.plugins",
artifactId = "android-junit5",
- currentVersion = "1.5.1.1-SNAPSHOT",
- latestStableVersion = "1.5.0.0",
+ currentVersion = "1.5.2.0",
+ latestStableVersion = "1.5.1.0",
license = license,
description = "Unit Testing with JUnit 5 for Android."
)
diff --git a/buildSrc/src/main/kotlin/Tasks.kt b/buildSrc/src/main/kotlin/Tasks.kt
index cf63bccc..079680bc 100644
--- a/buildSrc/src/main/kotlin/Tasks.kt
+++ b/buildSrc/src/main/kotlin/Tasks.kt
@@ -1,7 +1,5 @@
import org.gradle.api.DefaultTask
-import org.gradle.api.tasks.InputFiles
-import org.gradle.api.tasks.OutputDirectory
-import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.*
import java.io.File
/**
@@ -32,3 +30,82 @@ open class WriteClasspathResource : DefaultTask() {
}
}
}
+
+/**
+ * Helper Task class for generating an up-to-date version of the project's README.md.
+ * Using a template file, the plugin's version constants & other dependency versions
+ * are automatically injected into the README.
+ */
+open class GenerateReadme : DefaultTask() {
+
+ companion object {
+ private val PLACEHOLDER_REGEX = Regex("\\\$\\{(.+)}")
+ private val EXTERNAL_DEP_REGEX = Regex("Versions\\.(.+)")
+
+ private const val PLUGIN_VERSION = "pluginVersion"
+ private const val INSTRUMENTATION_VERSION = "instrumentationVersion"
+ }
+
+ @InputFile
+ lateinit var inputTemplateFile: File
+ @OutputFile
+ lateinit var outputFile: File
+
+ override fun getDescription() = "Generates the README.md file from a template"
+ override fun getGroup() = "documentation"
+
+ @TaskAction
+ fun doWork() {
+ val templateText = inputTemplateFile.readText()
+ val replacedText = replacePlaceholdersInTemplate(templateText)
+ outputFile.writeText(replacedText)
+ }
+
+ /* Private */
+
+ private fun replacePlaceholdersInTemplate(templateText: String): String {
+ // Apply placeholders in the template with data from Versions.kt & Artifacts.kt:
+ // ${pluginVersion} Artifacts.Plugin.currentVersion
+ // ${instrumentationVersion} Artifacts.Instrumentation.Core.currentVersion
+ // ${Versions.} (A constant value taken from Versions.kt)
+ val allPlaceholders = mutableMapOf()
+
+ PLACEHOLDER_REGEX.findAll(templateText).forEach { match ->
+ val placeholder = match.groups.last()?.value
+ ?: throw InvalidPlaceholder(match)
+
+ // Local versions (plugin, instrumentation)
+ val replacement = when (placeholder) {
+ PLUGIN_VERSION -> Artifacts.Plugin.anyStableVersion
+ INSTRUMENTATION_VERSION -> Artifacts.Instrumentation.Core.anyStableVersion
+ else -> {
+ val match2 = EXTERNAL_DEP_REGEX.find(placeholder)
+ ?: throw InvalidPlaceholder(match)
+ val externalDependency = match2.groups.last()?.value
+ ?: throw InvalidPlaceholder(match2)
+
+ val field = Versions.javaClass.getField(externalDependency)
+ field.get(null) as String
+ }
+ }
+
+ // Save placeholder
+ allPlaceholders["\${$placeholder}"] = replacement
+ }
+
+ var replacedText = templateText
+ allPlaceholders.forEach { (key, value) ->
+ replacedText = replacedText.replace(key, value)
+ }
+ return replacedText
+ }
+}
+
+private class InvalidPlaceholder(matchResult: MatchResult) : Exception("Invalid match result: '${matchResult.groupValues}'")
+
+private val Deployed.anyStableVersion: String
+ get() = if (currentVersion.endsWith("-SNAPSHOT")) {
+ latestStableVersion
+ } else {
+ currentVersion
+ }
diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt
index fb1d25e6..82dc4cc2 100644
--- a/buildSrc/src/main/kotlin/Versions.kt
+++ b/buildSrc/src/main/kotlin/Versions.kt
@@ -18,8 +18,8 @@ object Versions {
const val com_android_tools_build_gradle_32x: String = "3.2.1"
const val com_android_tools_build_gradle_33x: String = "3.3.2"
const val com_android_tools_build_gradle_34x: String = "3.4.2"
- const val com_android_tools_build_gradle_35x: String = "3.5.0-rc01"
- const val com_android_tools_build_gradle_36x: String = "3.6.0-alpha05"
+ const val com_android_tools_build_gradle_35x: String = "3.5.1"
+ const val com_android_tools_build_gradle_36x: String = "3.6.0-alpha12"
const val com_android_tools_build_gradle: String = "3.4.2"
const val lint_gradle: String = "26.2.1"
@@ -65,11 +65,11 @@ object Versions {
const val junit_pioneer: String = "0.2.2" // available: "0.3.0"
- const val org_junit_jupiter: String = "5.5.1"
+ const val org_junit_jupiter: String = "5.5.2"
- const val org_junit_platform: String = "1.5.1"
+ const val org_junit_platform: String = "1.5.2"
- const val junit_vintage_engine: String = "5.5.1"
+ const val junit_vintage_engine: String = "5.5.2"
const val mockito_core: String = "2.19.0" // available: "2.23.4"
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 4b7e1f3d..7c4388a9 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/plugin/.idea/runConfigurations/Generate_README_md.xml b/plugin/.idea/runConfigurations/Generate_README_md.xml
new file mode 100644
index 00000000..9efc9190
--- /dev/null
+++ b/plugin/.idea/runConfigurations/Generate_README_md.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+