-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add a gradle plugin #30
Conversation
Warning Rate Limit Exceeded@warnyul has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 17 minutes and 5 seconds before requesting another review. How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. WalkthroughThis update enhances a project's Gradle configuration by integrating a new plugin for JUnit 5 and Robolectric, improving Maven Central publishing setups, and updating GitHub Actions to include a new publishing step. It also extends repository configurations and updates dependencies, ensuring a streamlined development and deployment process for Android testing frameworks. Changes
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (invoked as PR comments)
Additionally, you can add CodeRabbit Configration File (
|
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0a47460..8a04822 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,8 +22,15 @@ jobs: distribution: 'temurin' - name: Setup Gradle uses: gradle/actions@db19848 # v3.3.2 + - name: Publish Gradle Plugin + run: | + ./publishGradlePlugin.sh + env: + JUNIT5_ROBOLECTRIC_EXTENSION_GRADLE_PLUGIN_PORTAL_KEY: '${{ secrets.JUNIT5_ROBOLECTRIC_EXTENSION_GRADLE_PLUGIN_PORTAL_KEY }}' + JUNIT5_ROBOLECTRIC_EXTENSION_GRADLE_PLUGIN_PORTAL_SECRET: '${{ secrets.JUNIT5_ROBOLECTRIC_EXTENSION_GRADLE_PLUGIN_PORTAL_SECRET }}' - name: Build with Gradle Wrapper - run: ./gradlew build koverXmlReport publish + run: | + ./gradlew build koverXmlReport publish env: JUNIT5_ROBOLECTRIC_EXTENSION_MAVEN_USERNAME: '${{ secrets.JUNIT5_ROBOLECTRIC_EXTENSION_MAVEN_USERNAME }}' JUNIT5_ROBOLECTRIC_EXTENSION_MAVEN_PASSWORD: '${{ secrets.JUNIT5_ROBOLECTRIC_EXTENSION_MAVEN_PASSWORD }}' diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 9efa103..b91666f 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -26,6 +26,7 @@ <option value="$PROJECT_DIR$/integration-tests/agp-groovy-dsl" /> <option value="$PROJECT_DIR$/integration-tests/agp-kotlin-dsl" /> <option value="$PROJECT_DIR$/robolectric-extension" /> + <option value="$PROJECT_DIR$/robolectric-extension-gradle-plugin" /> </set> </option> <option name="resolveExternalAnnotations" value="false" /> diff --git a/README.md b/README.md index 2caaf66..c72b713 100644 --- a/README.md +++ b/README.md @@ -21,14 +21,25 @@ in-memory environment. ## Installation -1. Add the Maven Central repository to your project's `build.gradle`: +1. Add the Gradle Plugin Portal and Maven Central and Google's Maven repository to your project's `settings.gradle` file: <details open> <summary>Kotlin</summary> ```kotlin -repositories { - mavenCentral() +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + google() + } +} + +dependencyResolutionManagement { + repositories { + mavenCentral() + google() + } } ``` @@ -38,8 +49,19 @@ repositories { <summary>Groovy</summary> ```groovy -repositories { - mavenCentral() +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + google() + } +} + +dependencyResolutionManagement { + repositories { + mavenCentral() + google() + } } ``` @@ -52,30 +74,8 @@ repositories { <summary>Kotlin</summary> ```kotlin -android { - testOptions { - unitTests { - isIncludeAndroidResources = true - all { test -> - test.useJUnitPlatform() - test.jvmArgs( - listOf( - "-Djunit.platform.launcher.interceptors.enabled=true", - "--add-exports", "java.base/jdk.internal.loader=ALL-UNNAMED", - "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", - ) - ) - } - } - } -} - -dependencies { - testImplementation("tech.apter.junit.jupiter:robolectric-extension:<latest.release>") - testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:<latest.release>") // JUnit 5 Jupiter Engine - // Optional dependencies if you want to use different version than used by the extension - testImplementation("org.junit.jupiter:junit-jupiter-api:<latest.release>") // Latest JUnit 5 Jupiter API - testImplementation("org.robolectric:robolectric:<latest.release>") // Latest Robolectric version +plugins { + id("tech.apter.junit5.jupiter.robolectric-extension-gradle-plugin") } ``` @@ -85,29 +85,8 @@ dependencies { <summary>Groovy</summary> ```groovy -android { - testOptions { - unitTests { - includeAndroidResources = true - all { - useJUnitPlatform() - jvmArgs( - '-Djunit.platform.launcher.interceptors.enabled=true', - '--add-exports', 'java.base/jdk.internal.loader=ALL-UNNAMED', - '--add-opens', 'java.base/jdk.internal.loader=ALL-UNNAMED', - ) - } - } - } -} - -dependencies { - testImplementation 'tech.apter.junit.jupiter:robolectric-extension:<latest.release>' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:<latest.release>' - // Latest JUnit 5 Jupiter Engine - // Optional dependencies if you want to use different versions than used by the extension - testImplementation 'org.junit.jupiter:junit-jupiter-api:<latest.release>' // Latest JUnit 5 Jupiter API - testImplementation 'org.robolectric:robolectric:<latest.release>' // Latest Robolectric version +plugins { + id 'tech.apter.junit5.jupiter.robolectric-extension-gradle-plugin' } ``` @@ -270,10 +249,5 @@ public class RobolectricExtensionSelfTest { ## Important Notes -* Ensure `isIncludeAndroidResources` is set to true in your testOptions configuration to access - Android resources in your tests. -* JUnit Platform Launcher Interceptors must be - enabled (`junit.platform.launcher.interceptors.enabled=true`), otherwise - test instances will not be created by Robolectric's classloader. * Parallel execution is currently not supported. Run tests sequentially for now. diff --git a/build.gradle b/build.gradle index cdd3977..f9542bc 100644 --- a/build.gradle +++ b/build.gradle @@ -7,8 +7,17 @@ allprojects { version = property('tech.apter.junit5.robolectric.extension.version') } +subprojects { + configurations.configureEach { + resolutionStrategy.dependencySubstitution { + substitute module("tech.apter.junit5.jupiter:robolectric-extension:$version") using project(':robolectric-extension') + } + } +} + dependencies { kover(project(':integration-tests:agp-groovy-dsl')) kover(project(':integration-tests:agp-kotlin-dsl')) kover(project(':robolectric-extension')) + kover(project(':robolectric-extension-gradle-plugin')) } diff --git a/gradle/dokka.gradle b/gradle/dokka.gradle new file mode 100644 index 0000000..ebb32eb --- /dev/null +++ b/gradle/dokka.gradle @@ -0,0 +1,5 @@ +tasks.register('dokkaJavadocJar', Jar) { + dependsOn dokkaJavadoc + archiveClassifier.set 'javadoc' + from javadoc.destinationDir +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 01785af..4b94201 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,8 +4,10 @@ androidCompileSdk = "34" androidGradle = "8.3.2" androidMinimumSdk = "14" androidxTestExtJunit = "1.1.5" +buildConfig = "5.3.5" detekt = "1.23.6" dokka = "1.9.20" +gradlePluginPublish = "1.2.1" guava = "33.1.0-jre" junit4 = "4.13.2" junit5 = "5.10.2" @@ -37,8 +39,10 @@ robolectricAndroidAll = { module = "org.robolectric:android-all", version.ref = [plugins] androidLibrary = { id = "com.android.library", version.ref = "androidGradle" } +buildConfig = { id = "com.github.gmazzo.buildconfig", version.ref = "buildConfig" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } +gradlePluginPublish = { id = "com.gradle.plugin-publish", version.ref = "gradlePluginPublish" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlinxKover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } diff --git a/gradle/pom.gradle b/gradle/pom.gradle new file mode 100644 index 0000000..46a8cb9 --- /dev/null +++ b/gradle/pom.gradle @@ -0,0 +1,37 @@ +final void setupPom(final MavenPublication publication, final String publicationName) { + publication.pom { pom -> + name = publicationName + description = """This repository aims to bridge the gap between JUnit 5 and Robolectric, + |enabling developers to leverage the benefits of both frameworks + |for unit testing Android applications. While Robolectric currently lacks + |a dedicated JUnit 5 extension, this project proposes a community-driven solution to + |achieve seamless integration.""".stripMargin() + url = 'https://github.com/apter-tech/junit5-robolectric-extension' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + organization { + name = 'Apter Technologies Ltd.' + url = 'https://apter.tech' + } + developers { + developer { + id = 'warnyul' + name = 'Balázs Varga' + email = '[email protected]' + } + } + scm { + connection = 'scm:git:git://github.com:apter-tech/junit5-robolectric-extension.git' + developerConnection = 'scm:git:ssh://github.com:apter-tech/junit5-robolectric-extension.git' + url = 'https://github.com/apter-tech/junit5-robolectric-extension' + } + } +} + +ext { + setupPom = this.&setupPom +} diff --git a/gradle/publishing.gradle b/gradle/publishing.gradle deleted file mode 100644 index 6231c22..0000000 --- a/gradle/publishing.gradle +++ /dev/null @@ -1,79 +0,0 @@ -apply plugin: 'maven-publish' -apply plugin: 'signing' - -tasks.register('dokkaJavadocJar', Jar) { - dependsOn dokkaJavadoc - archiveClassifier.set 'javadoc' - from javadoc.destinationDir -} - -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - artifact(kotlinSourcesJar) - artifact(dokkaJavadocJar) - - pom { - name = 'JUnit5 Robolectric Extension' - description = """This repository aims to bridge the gap between JUnit 5 and Robolectric, - |enabling developers to leverage the benefits of both frameworks - |for unit testing Android applications. While Robolectric currently lacks - |a dedicated JUnit 5 extension, this project proposes a community-driven solution to - |achieve seamless integration.""".stripMargin() - url = 'https://github.com/apter-tech/junit5-robolectric-extension' - licenses { - license { - name = 'The Apache License, Version 2.0' - url = 'https://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - organization { - name = 'Apter Technologies Ltd.' - url = 'https://apter.tech' - } - developers { - developer { - id = 'warnyul' - name = 'Balázs Varga' - email = '[email protected]' - } - } - scm { - connection = 'scm:git:git://github.com:apter-tech/junit5-robolectric-extension.git' - developerConnection = 'scm:git:ssh://github.com:apter-tech/junit5-robolectric-extension.git' - url = 'https://github.com/apter-tech/junit5-robolectric-extension' - } - } - } - } - repositories { - maven { - name = 'MavenCentral' - final releasesRepoUrl = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2' - final snapshotsRepoUrl = 'https://s01.oss.sonatype.org/content/repositories/snapshots' - url = version.toString().endsWith("SNAPSHOT") ? snapshotsRepoUrl : releasesRepoUrl - credentials { - username = System.getenv('JUNIT5_ROBOLECTRIC_EXTENSION_MAVEN_USERNAME') - password = System.getenv('JUNIT5_ROBOLECTRIC_EXTENSION_MAVEN_PASSWORD') - } - } - } -} - -final JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_KEY = System.getenv( - 'JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_KEY' -) ?: "" -final JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_PASSWORD = System.getenv( - 'JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_PASSWORD' -) ?: "" - -if (!JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_KEY.isEmpty() && !JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_PASSWORD.isEmpty()) { - signing { - useInMemoryPgpKeys( - JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_KEY, - JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_PASSWORD, - ) - sign(publishing.publications["mavenJava"]) - } -} diff --git a/gradle/setupMavenCentralForPublishing.gradle b/gradle/setupMavenCentralForPublishing.gradle new file mode 100644 index 0000000..06d44ec --- /dev/null +++ b/gradle/setupMavenCentralForPublishing.gradle @@ -0,0 +1,16 @@ +apply plugin: 'maven-publish' + +publishing { + repositories { + maven { + name = 'MavenCentral' + final releasesRepoUrl = 'https://s01.oss.sonatype.org/service/local/staging/deploy/maven2' + final snapshotsRepoUrl = 'https://s01.oss.sonatype.org/content/repositories/snapshots' + url = version.toString().endsWith("SNAPSHOT") ? snapshotsRepoUrl : releasesRepoUrl + credentials { + username = System.getenv('JUNIT5_ROBOLECTRIC_EXTENSION_MAVEN_USERNAME') + password = System.getenv('JUNIT5_ROBOLECTRIC_EXTENSION_MAVEN_PASSWORD') + } + } + } +} diff --git a/gradle/signing.gradle b/gradle/signing.gradle new file mode 100644 index 0000000..2ac41e4 --- /dev/null +++ b/gradle/signing.gradle @@ -0,0 +1,18 @@ +final JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_KEY = System.getenv( + 'JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_KEY' +) ?: "" +final JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_PASSWORD = System.getenv( + 'JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_PASSWORD' +) ?: "" + +if (!JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_KEY.isEmpty() && !JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_PASSWORD.isEmpty()) { + apply plugin: 'signing' + + signing { + useInMemoryPgpKeys( + JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_KEY, + JUNIT5_ROBOLECTRIC_EXTENSION_GPG_SIGNING_PASSWORD, + ) + sign(publishing.publications) + } +} diff --git a/integration-tests/agp-groovy-dsl/build.gradle b/integration-tests/agp-groovy-dsl/build.gradle index 642ce0d..f829f67 100644 --- a/integration-tests/agp-groovy-dsl/build.gradle +++ b/integration-tests/agp-groovy-dsl/build.gradle @@ -1,3 +1,11 @@ +import tech.apter.robolectric.junit.jupiter.gradle.plugin.RobolectricJUnitJupiterGradlePlugin + +buildscript { + dependencies { + classpath("tech.apter.junit5.jupiter:robolectric-extension-gradle-plugin:$version") + } +} + plugins { id('com.android.library') alias(libs.plugins.kotlinAndroid) @@ -5,6 +13,8 @@ plugins { alias(libs.plugins.detekt) } +apply plugin: RobolectricJUnitJupiterGradlePlugin + android { namespace = 'tech.apter.junit.jupiter.robolectric.integration.tests.agp.groovy.dsl' compileSdk = libs.versions.androidCompileSdk.get().toInteger() @@ -13,20 +23,6 @@ android { defaultConfig { minSdk = libs.versions.androidMinimumSdk.get().toInteger() } - - testOptions { - unitTests { - includeAndroidResources = true - all { - useJUnitPlatform() - jvmArgs( - '--add-exports', 'java.base/jdk.internal.loader=ALL-UNNAMED', - '--add-opens', 'java.base/jdk.internal.loader=ALL-UNNAMED', - '-Djunit.platform.launcher.interceptors.enabled=true' - ) - } - } - } } detekt { @@ -41,8 +37,4 @@ kotlin { dependencies { detektPlugins(libs.detektFormatting) detektPlugins(libs.detektRulesLibraries) - testImplementation(project(':robolectric-extension')) - testImplementation(libs.robolectric) - testImplementation(libs.junit5JupiterApi) - testRuntimeOnly(libs.junit5JupiterEngine) } diff --git a/integration-tests/agp-kotlin-dsl/build.gradle.kts b/integration-tests/agp-kotlin-dsl/build.gradle.kts index 6c2827d..c65ef95 100644 --- a/integration-tests/agp-kotlin-dsl/build.gradle.kts +++ b/integration-tests/agp-kotlin-dsl/build.gradle.kts @@ -1,3 +1,11 @@ +import tech.apter.robolectric.junit.jupiter.gradle.plugin.RobolectricJUnitJupiterGradlePlugin + +buildscript { + dependencies { + classpath("tech.apter.junit5.jupiter:robolectric-extension-gradle-plugin:$version") + } +} + plugins { id("com.android.library") alias(libs.plugins.kotlinAndroid) @@ -5,6 +13,8 @@ plugins { alias(libs.plugins.detekt) } +apply(mapOf("plugin" to RobolectricJUnitJupiterGradlePlugin::class.java)) + android { namespace = "tech.apter.junit.jupiter.robolectric.integration.tests.agp.kotlin.dsl" compileSdk = libs.versions.androidCompileSdk.get().toInt() @@ -13,23 +23,6 @@ android { defaultConfig { minSdk = libs.versions.androidMinimumSdk.get().toInt() } - - @Suppress("UnstableApiUsage") - testOptions { - unitTests { - isIncludeAndroidResources = true - all { test -> - test.useJUnitPlatform() - test.jvmArgs( - listOf( - "--add-exports", "java.base/jdk.internal.loader=ALL-UNNAMED", - "--add-opens", "java.base/jdk.internal.loader=ALL-UNNAMED", - "-Djunit.platform.launcher.interceptors.enabled=true" - ) - ) - } - } - } } detekt { @@ -44,8 +37,4 @@ kotlin { dependencies { detektPlugins(libs.detektFormatting) detektPlugins(libs.detektRulesLibraries) - testImplementation(project(":robolectric-extension")) - testImplementation(libs.robolectric) - testImplementation(libs.junit5JupiterApi) - testRuntimeOnly(libs.junit5JupiterEngine) } diff --git a/publishGradlePlugin.sh b/publishGradlePlugin.sh new file mode 100755 index 0000000..a1968e5 --- /dev/null +++ b/publishGradlePlugin.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +function publishGradlePlugin() { + ./gradlew :robolectric-extension-gradle-plugin:publishToMavenLocal --configure-on-demand + local -r robolectricGradlePluginVersion=$(cat < gradle.properties | grep tech.apter.junit5.robolectric.extension.version | cut -d'=' -f2) + + if [[ "$robolectricGradlePluginVersion" != *SNAPSHOT ]]; then + ./gradlew :robolectric-extension-gradle-plugin:publishPlugins \ + --configure-on-demand \ + -D"gradle.publish.key=${JUNIT5_ROBOLECTRIC_EXTENSION_GRADLE_PLUGIN_PORTAL_KEY}" \ + -D"gradle.publish.secret=${JUNIT5_ROBOLECTRIC_EXTENSION_GRADLE_PLUGIN_PORTAL_SECRET}" + fi +} + +publishGradlePlugin diff --git a/robolectric-extension-gradle-plugin/build.gradle b/robolectric-extension-gradle-plugin/build.gradle new file mode 100644 index 0000000..328e338 --- /dev/null +++ b/robolectric-extension-gradle-plugin/build.gradle @@ -0,0 +1,62 @@ +plugins { + id('java-gradle-plugin') + alias(libs.plugins.kotlinJvm) + alias(libs.plugins.buildConfig) + alias(libs.plugins.detekt) + alias(libs.plugins.dokka) + alias(libs.plugins.kotlinxKover) + id('maven-publish') + id('signing') + alias(libs.plugins.gradlePluginPublish) +} + +buildConfig { + useKotlinOutput() + packageName('tech.apter.robolectric.junit.jupiter.gradle.plugin') + buildConfigField(String, 'ROBOLECTRIC_EXTENSION_VERSION', project.version) + buildConfigField(String, 'JUNIT5_BOM_VERSION', libs.junit5Bom.get().version) +} + +kotlin { + jvmToolchain(libs.versions.jvmToolchain.get().toInteger()) +} + +detekt { + toolVersion = libs.versions.detekt.get() + autoCorrect true +} + +dependencies { + detektPlugins(libs.detektFormatting) + detektPlugins(libs.detektRulesLibraries) + compileOnly(gradleApi()) + compileOnly(libs.androidGradle) +} + +gradlePlugin { + website = 'https://github.com/apter-tech/junit5-robolectric-extension' + vcsUrl = 'https://github.com/apter-tech/junit5-robolectric-extension.git' + plugins { + robolectricJUnitJupiterGradlePlugin { + id = 'tech.apter.junit5.jupiter.robolectric-extension-gradle-plugin' + displayName = 'JUnit5 Robolectric Extension Gradle Plugin' + description = """This repository aims to bridge the gap between JUnit 5 and Robolectric, + |enabling developers to leverage the benefits of both frameworks + |for unit testing Android applications. While Robolectric currently lacks + |a dedicated JUnit 5 extension, this project proposes a community-driven solution to + |achieve seamless integration.""".stripMargin() + tags.addAll('Robolectric', 'JUnit5', 'JUnit Jupiter', 'androidTesting', 'testing', 'android') + implementationClass = 'tech.apter.robolectric.junit.jupiter.gradle.plugin.RobolectricJUnitJupiterGradlePlugin' + } + } +} + +apply from: "${rootProject.layout.projectDirectory.file('gradle/pom.gradle')}" +publishing { + publications.withType(MavenPublication).configureEach { + setupPom(it, 'JUnit5 Robolectric Extension Gradle Plugin') + } +} +apply from: "${rootProject.layout.projectDirectory.file('gradle/setupMavenCentralForPublishing.gradle')}" +apply from: "${rootProject.layout.projectDirectory.file('gradle/signing.gradle')}" + diff --git a/robolectric-extension-gradle-plugin/src/main/kotlin/tech/apter/robolectric/junit/jupiter/gradle/plugin/RobolectricJUnitJupiterGradlePlugin.kt b/robolectric-extension-gradle-plugin/src/main/kotlin/tech/apter/robolectric/junit/jupiter/gradle/plugin/RobolectricJUnitJupiterGradlePlugin.kt new file mode 100644 index 0000000..cc6b3aa --- /dev/null +++ b/robolectric-extension-gradle-plugin/src/main/kotlin/tech/apter/robolectric/junit/jupiter/gradle/plugin/RobolectricJUnitJupiterGradlePlugin.kt @@ -0,0 +1,70 @@ +package tech.apter.robolectric.junit.jupiter.gradle.plugin + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.logging.Logging +import org.gradle.api.tasks.testing.Test + +@Suppress("LibraryEntitiesShouldNotBePublic") +class RobolectricJUnitJupiterGradlePlugin : Plugin<Project> { + private inline val logger get() = Logging.getLogger(javaClass) + + override fun apply(target: Project) { + logger.trace("${javaClass.name} is applied.") + + with(target) { + val extension = registerExtension() + setupTestTasks() + enableIncludeAndroidResources() + afterEvaluate { + if (!extension.doNotAddDependencies) { + addDependencies() + } + } + } + } + + private fun Project.registerExtension(): RobolectricJUnitJupiterGradlePluginExtension = extensions.create( + "robolectricJUnitJupiter", + RobolectricJUnitJupiterGradlePluginExtension::class.java, + /* doNotAddDependencies= */ + false, + ) + + private fun Project.setupTestTasks() { + val jvmArgs = listOf( + "--add-exports", + "java.base/jdk.internal.loader=ALL-UNNAMED", + "--add-opens", + "java.base/jdk.internal.loader=ALL-UNNAMED", + "-Djunit.platform.launcher.interceptors.enabled=true", + ) + tasks.withType(Test::class.java).configureEach { testTask -> + testTask.useJUnitPlatform() + testTask.jvmArgs(jvmArgs) + } + tasks.whenTaskAdded { task -> + if (task is Test) { + task.useJUnitPlatform() + task.jvmArgs(jvmArgs) + } + } + } + + private fun Project.enableIncludeAndroidResources() { + val androidExtension = extensions.findByName("android") as? CommonExtension<*, *, *, *, *, *> + androidExtension?.testOptions?.unitTests?.isIncludeAndroidResources = true + } + + private fun Project.addDependencies() { + with(dependencies) { + add( + "testImplementation", + "tech.apter.junit5.jupiter:robolectric-extension:${BuildConfig.ROBOLECTRIC_EXTENSION_VERSION}" + ) + add("testImplementation", platform("org.junit:junit-bom:${BuildConfig.JUNIT5_BOM_VERSION}")) + add("testRuntimeOnly", "org.junit.jupiter:junit-jupiter-engine") + } + } +} diff --git a/robolectric-extension-gradle-plugin/src/main/kotlin/tech/apter/robolectric/junit/jupiter/gradle/plugin/RobolectricJUnitJupiterGradlePluginExtension.kt b/robolectric-extension-gradle-plugin/src/main/kotlin/tech/apter/robolectric/junit/jupiter/gradle/plugin/RobolectricJUnitJupiterGradlePluginExtension.kt new file mode 100644 index 0000000..1de5bbf --- /dev/null +++ b/robolectric-extension-gradle-plugin/src/main/kotlin/tech/apter/robolectric/junit/jupiter/gradle/plugin/RobolectricJUnitJupiterGradlePluginExtension.kt @@ -0,0 +1,4 @@ +package tech.apter.robolectric.junit.jupiter.gradle.plugin + +@Suppress("LibraryEntitiesShouldNotBePublic") +open class RobolectricJUnitJupiterGradlePluginExtension(var doNotAddDependencies: Boolean) diff --git a/robolectric-extension/build.gradle b/robolectric-extension/build.gradle index 36abd66..dd9681f 100644 --- a/robolectric-extension/build.gradle +++ b/robolectric-extension/build.gradle @@ -1,13 +1,22 @@ import org.robolectric.gradle.AarDepsPlugin +import tech.apter.robolectric.junit.jupiter.gradle.plugin.RobolectricJUnitJupiterGradlePlugin + +buildscript { + dependencies { + classpath("tech.apter.junit5.jupiter:robolectric-extension-gradle-plugin:$version") + } +} plugins { alias(libs.plugins.kotlinJvm) alias(libs.plugins.kotlinxKover) alias(libs.plugins.detekt) alias(libs.plugins.dokka) + id('maven-publish') } apply plugin: AarDepsPlugin +apply plugin: RobolectricJUnitJupiterGradlePlugin configurations.configureEach { configuration -> configuration.exclude(group: 'androidx.tracing', module: 'tracing') @@ -18,19 +27,17 @@ kotlin { jvmToolchain(libs.versions.jvmToolchain.get().toInteger()) } +robolectricJUnitJupiter { + doNotAddDependencies = true +} + test { - useJUnitPlatform() testLogging { showStandardStreams = true showExceptions = true showCauses = true showStackTraces = true } - jvmArgs( - '--add-exports', 'java.base/jdk.internal.loader=ALL-UNNAMED', - '--add-opens', 'java.base/jdk.internal.loader=ALL-UNNAMED', - ) - systemProperty 'junit.platform.launcher.interceptors.enabled', 'true' systemProperty 'junit.jupiter.execution.parallel.enabled', 'true' systemProperty 'junit.jupiter.execution.parallel.mode.default ', 'same_thread' systemProperty 'junit.jupiter.execution.parallel.mode.classes.default', 'same_thread' @@ -103,4 +110,20 @@ tasks.register('generateAndroidR') { } } -apply from: "${rootProject.layout.projectDirectory.file('gradle/publishing.gradle')}" +apply from: "${rootProject.layout.projectDirectory.file('gradle/dokka.gradle')}" +apply from: "${rootProject.layout.projectDirectory.file('gradle/pom.gradle')}" + +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact(kotlinSourcesJar) + artifact(dokkaJavadocJar) + + setupPom(it, 'JUnit5 Robolectric Extension') + } + } +} + +apply from: "${rootProject.layout.projectDirectory.file('gradle/setupMavenCentralForPublishing.gradle')}" +apply from: "${rootProject.layout.projectDirectory.file('gradle/signing.gradle')}" diff --git a/settings.gradle b/settings.gradle index 4d65571..656e9ce 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,6 +3,7 @@ pluginManagement { gradlePluginPortal() mavenCentral() google() + mavenLocal() } } @@ -21,4 +22,5 @@ rootProject.name = 'junit5-robolectric-extension' include('integration-tests:agp-groovy-dsl') include('integration-tests:agp-kotlin-dsl') include('robolectric-extension') +include('robolectric-extension-gradle-plugin')
Branch Coverage
|
Line Coverage
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Out of diff range and nitpick comments (1)
README.md (1)
121-122
: Consider a more formal alternative to "if you want to."Instead of "if you want to," consider using "as needed" or "if required" to elevate the formality of the documentation.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Chores