From 81280fd0aff1817f754bdc03a584df15d797b0df Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Wed, 22 May 2024 16:19:38 +0200 Subject: [PATCH] Use new Variant API for generated instrumentation filter file (#336) * Add unit tests for write-filters task & fix a bug with generating the filters file for instrumentation tests * Replace resource folder generation for instrumentation filters with new Variant API Since the minimum AGP version bump, we can finally safely access the source directories across all supported versions * Update API definition to reflect changes to the filters task * Changelog --- plugin/CHANGELOG.md | 1 + plugin/android-junit5/api/android-junit5.api | 9 +- .../junit5/internal/config/PluginConfig.kt | 7 -- .../junit5/internal/configureJUnit5.kt | 10 +-- .../internal/extensions/BaseVariantExt.kt | 10 --- .../junit5/internal/extensions/VariantExt.kt | 5 ++ .../junit5/tasks/AndroidJUnit5WriteFilters.kt | 87 +++++++++---------- .../plugin/AgpInstrumentationSupportTests.kt | 12 +-- .../plugin/InstrumentationSupportTests.kt | 10 +++ .../tasks/AndroidJUnit5WriteFiltersTests.kt | 77 ++++++++++++++++ .../gradle/plugins/junit5/util/GradleTruth.kt | 19 ++++ .../util/projects/PluginSpecProjectCreator.kt | 22 ++++- 12 files changed, 186 insertions(+), 83 deletions(-) create mode 100644 plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFiltersTests.kt diff --git a/plugin/CHANGELOG.md b/plugin/CHANGELOG.md index 24853bf4..ec165b44 100644 --- a/plugin/CHANGELOG.md +++ b/plugin/CHANGELOG.md @@ -12,6 +12,7 @@ Change Log - Decouple discovery of instrumentation tests from Jupiter, allowing non-Jupiter test engines to be discovered as well - Update lifecycle of instrumentation runner params to only be set once, instead of once per test - Properly reported disabled dynamic tests to Android instrumentation +- Use new Variant API to register generated resource folder for instrumentation filters file ## 1.10.0.0 (2023-11-05) - JUnit 5.10.0 diff --git a/plugin/android-junit5/api/android-junit5.api b/plugin/android-junit5/api/android-junit5.api index e37b6f8f..0d182798 100644 --- a/plugin/android-junit5/api/android-junit5.api +++ b/plugin/android-junit5/api/android-junit5.api @@ -61,11 +61,8 @@ public abstract class de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5J public abstract class de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFilters : org/gradle/api/DefaultTask { public fun ()V public final fun execute ()V - public final fun getExcludeTags ()Ljava/util/List; - public final fun getIncludeTags ()Ljava/util/List; - public final fun getOutputFolder ()Ljava/io/File; - public final fun setExcludeTags (Ljava/util/List;)V - public final fun setIncludeTags (Ljava/util/List;)V - public final fun setOutputFolder (Ljava/io/File;)V + public abstract fun getExcludeTags ()Lorg/gradle/api/provider/ListProperty; + public abstract fun getIncludeTags ()Lorg/gradle/api/provider/ListProperty; + public abstract fun getOutputFolder ()Lorg/gradle/api/file/DirectoryProperty; } diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt index 724de38c..25feb0eb 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt @@ -13,8 +13,6 @@ import com.android.build.gradle.DynamicFeaturePlugin import com.android.build.gradle.LibraryExtension import com.android.build.gradle.LibraryPlugin import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.TestVariant -import de.mannodermaus.gradle.plugins.junit5.internal.extensions.instrumentationTestVariant import de.mannodermaus.gradle.plugins.junit5.internal.providers.DirectoryProvider import de.mannodermaus.gradle.plugins.junit5.internal.providers.JavaDirectoryProvider import de.mannodermaus.gradle.plugins.junit5.internal.providers.KotlinDirectoryProvider @@ -68,11 +66,6 @@ private constructor( ?: emptySet() } - fun instrumentationTestVariantOf(variant: Variant): TestVariant? { - return legacyVariants.firstOrNull { it.name == variant.name } - ?.run { this.instrumentationTestVariant } - } - /* Private */ private fun directoryProvidersOf(legacyVariant: BaseVariant): Set { diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/configureJUnit5.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/configureJUnit5.kt index 144e33ac..7650819c 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/configureJUnit5.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/configureJUnit5.kt @@ -14,7 +14,7 @@ import de.mannodermaus.gradle.plugins.junit5.internal.config.PluginConfig import de.mannodermaus.gradle.plugins.junit5.internal.extensions.android import de.mannodermaus.gradle.plugins.junit5.internal.extensions.getAsList import de.mannodermaus.gradle.plugins.junit5.internal.extensions.getTaskName -import de.mannodermaus.gradle.plugins.junit5.internal.extensions.hasDependency +import de.mannodermaus.gradle.plugins.junit5.internal.extensions.instrumentationTestVariant import de.mannodermaus.gradle.plugins.junit5.internal.extensions.junit5Warn import de.mannodermaus.gradle.plugins.junit5.internal.extensions.namedOrNull import de.mannodermaus.gradle.plugins.junit5.internal.extensions.usesComposeIn @@ -23,7 +23,6 @@ import de.mannodermaus.gradle.plugins.junit5.internal.utils.excludedPackagingOpt import de.mannodermaus.gradle.plugins.junit5.tasks.AndroidJUnit5JacocoReport import de.mannodermaus.gradle.plugins.junit5.tasks.AndroidJUnit5WriteFilters import org.gradle.api.Project -import org.gradle.api.artifacts.Dependency import org.gradle.api.tasks.testing.Test internal fun configureJUnit5( @@ -51,7 +50,7 @@ internal fun configureJUnit5( variants.forEach { variant -> configureUnitTests(it, variant) configureJacoco(it, config, variant) - configureInstrumentationTests(it, config, variant) + configureInstrumentationTests(it, variant) } } } @@ -197,12 +196,11 @@ private fun AndroidJUnitPlatformExtension.configureJacoco( private fun AndroidJUnitPlatformExtension.configureInstrumentationTests( project: Project, - config: PluginConfig, variant: Variant, ) { if (!instrumentationTests.enabled.get()) return - config.instrumentationTestVariantOf(variant)?.let { instrumentationTestVariant -> - AndroidJUnit5WriteFilters.register(project, variant, instrumentationTestVariant) + variant.instrumentationTestVariant?.sources?.res?.let { sourceDirs -> + AndroidJUnit5WriteFilters.register(project, variant, sourceDirs) } } diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/extensions/BaseVariantExt.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/extensions/BaseVariantExt.kt index eec387ef..a2dd5eb9 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/extensions/BaseVariantExt.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/extensions/BaseVariantExt.kt @@ -3,7 +3,6 @@ package de.mannodermaus.gradle.plugins.junit5.internal.extensions import com.android.build.gradle.api.BaseVariant -import com.android.build.gradle.api.TestVariant import com.android.build.gradle.api.UnitTestVariant import com.android.build.gradle.internal.api.TestedVariant @@ -15,12 +14,3 @@ internal val BaseVariant.unitTestVariant: UnitTestVariant return requireNotNull(this.unitTestVariant) } - -internal val BaseVariant.instrumentationTestVariant: TestVariant? - get() { - if (this !is TestedVariant) { - throw IllegalArgumentException("Argument is not TestedVariant: $this") - } - - return this.testVariant - } diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/extensions/VariantExt.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/extensions/VariantExt.kt index 2c099c37..9b226f4e 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/extensions/VariantExt.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/extensions/VariantExt.kt @@ -1,5 +1,7 @@ package de.mannodermaus.gradle.plugins.junit5.internal.extensions +import com.android.build.api.variant.AndroidTest +import com.android.build.api.variant.HasAndroidTest import com.android.build.api.variant.Variant internal fun Variant.getTaskName(prefix: String = "", suffix: String = ""): String { @@ -18,3 +20,6 @@ internal fun Variant.getTaskName(prefix: String = "", suffix: String = ""): Stri append(suffix.capitalized()) }.toString() } + +internal val Variant.instrumentationTestVariant: AndroidTest? + get() = (this as? HasAndroidTest)?.androidTest diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFilters.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFilters.kt index e0af00c3..fd2a42d2 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFilters.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFilters.kt @@ -1,15 +1,15 @@ -@file:Suppress("DEPRECATION") - package de.mannodermaus.gradle.plugins.junit5.tasks +import com.android.build.api.variant.SourceDirectories import com.android.build.api.variant.Variant -import com.android.build.gradle.api.TestVariant import de.mannodermaus.gradle.plugins.junit5.internal.config.INSTRUMENTATION_FILTER_RES_FILE_NAME import de.mannodermaus.gradle.plugins.junit5.internal.config.JUnit5TaskConfig import de.mannodermaus.gradle.plugins.junit5.internal.extensions.getTaskName import de.mannodermaus.gradle.plugins.junit5.internal.extensions.junitPlatform import org.gradle.api.DefaultTask import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.ListProperty import org.gradle.api.tasks.CacheableTask import org.gradle.api.tasks.Input import org.gradle.api.tasks.OutputDirectory @@ -25,20 +25,20 @@ import java.io.File * This only allows tests to be filtered with @Tag annotations even in the instrumentation test realm. * Other plugin DSL settings, like includeEngines/excludeEngines or includePattern/excludePattern * are not copied out to file. This has to do with limitations of the backport implementation - * of the JUnit Platform Runner, as well as some incompatibilities between Gradle and Java with regards to - * how class name patterns are formatted. + * of the JUnit Platform Runner, as well as some incompatibilities between Gradle and Java + * regarding how class name patterns are formatted. */ @CacheableTask public abstract class AndroidJUnit5WriteFilters : DefaultTask() { internal companion object { + @Suppress("UnstableApiUsage") fun register( project: Project, variant: Variant, - instrumentationTestVariant: TestVariant + sourceDirs: SourceDirectories.Layered, ): Boolean { - val outputFolder = File("${project.buildDir}/generated/res/android-junit5/${instrumentationTestVariant.name}") - val configAction = ConfigAction(project, variant, outputFolder) + val configAction = ConfigAction(project, variant) val provider = project.tasks.register( configAction.name, @@ -48,54 +48,53 @@ public abstract class AndroidJUnit5WriteFilters : DefaultTask() { // Connect the output folder of the task to the instrumentation tests // so that they are bundled into the built test application - instrumentationTestVariant.registerGeneratedResFolders( - project.files(outputFolder).builtBy(provider) + sourceDirs.addGeneratedSourceDirectory( + taskProvider = provider, + wiredWith = AndroidJUnit5WriteFilters::outputFolder, ) - instrumentationTestVariant.mergeResourcesProvider.configure { it.dependsOn(provider) } return true } } - @Input - public var includeTags: List = emptyList() + @get:Input + public abstract val includeTags: ListProperty - @Input - public var excludeTags: List = emptyList() + @get:Input + public abstract val excludeTags: ListProperty - @OutputDirectory - public var outputFolder: File? = null + @get:OutputDirectory + public abstract val outputFolder: DirectoryProperty @TaskAction public fun execute() { - this.outputFolder?.let { folder -> - // Clear out current contents of the generated folder - folder.deleteRecursively() - - if (this.hasFilters()) { - folder.mkdirs() - - // Re-write the new file structure into it; - // the generated file will have a fixed name & is located - // as a "raw" resource inside the output folder - val rawFolder = File(folder, "raw").apply { mkdirs() } - File(rawFolder, INSTRUMENTATION_FILTER_RES_FILE_NAME) - .bufferedWriter() - .use { writer -> - // This format is a nod towards the real JUnit 5 ConsoleLauncher's arguments - includeTags.forEach { tag -> writer.write("-t $tag") } - excludeTags.forEach { tag -> writer.write("-T $tag") } - } - } + // Clear out current contents of the generated folder + val folder = outputFolder.get().asFile + folder.deleteRecursively() + + val includeTags = includeTags.get() + val excludeTags = excludeTags.get() + + if (includeTags.isNotEmpty() || excludeTags.isNotEmpty()) { + folder.mkdirs() + + // Re-write the new file structure into it; + // the generated file will have a fixed name & is located + // as a "raw" resource inside the output folder + val rawFolder = File(folder, "raw").apply { mkdirs() } + File(rawFolder, INSTRUMENTATION_FILTER_RES_FILE_NAME) + .bufferedWriter() + .use { writer -> + // This format is a nod towards the real JUnit 5 ConsoleLauncher's arguments + includeTags.forEach { tag -> writer.appendLine("-t $tag") } + excludeTags.forEach { tag -> writer.appendLine("-T $tag") } + } } } - private fun hasFilters() = includeTags.isNotEmpty() || excludeTags.isNotEmpty() - private class ConfigAction( private val project: Project, private val variant: Variant, - private val outputFolder: File ) { val name: String = variant.getTaskName(prefix = "writeFilters", suffix = "androidTest") @@ -103,12 +102,12 @@ public abstract class AndroidJUnit5WriteFilters : DefaultTask() { val type = AndroidJUnit5WriteFilters::class.java fun execute(task: AndroidJUnit5WriteFilters) { - task.outputFolder = outputFolder - - // Access filters for this particular variant & provide them to the task, too + // Access filters for this particular variant & provide them to the task val configuration = JUnit5TaskConfig(variant, project.junitPlatform) - task.includeTags = configuration.combinedIncludeTags.toList() - task.excludeTags = configuration.combinedExcludeTags.toList() + task.includeTags.set(configuration.combinedIncludeTags.toList()) + task.excludeTags.set(configuration.combinedExcludeTags.toList()) + + // Output folder is applied by Android Gradle Plugin, so there is no reason to provide a value ourselves } } } diff --git a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/plugin/AgpInstrumentationSupportTests.kt b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/plugin/AgpInstrumentationSupportTests.kt index 79ba9bb2..f30e198f 100644 --- a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/plugin/AgpInstrumentationSupportTests.kt +++ b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/plugin/AgpInstrumentationSupportTests.kt @@ -45,8 +45,8 @@ interface AgpInstrumentationSupportTests : AgpVariantAwareTests { val task = project.tasks.get("writeFiltersDebugAndroidTest") assertAll( { assertThat(task).isNotNull() }, - { assertThat(task.includeTags).containsExactly("global-include-tag") }, - { assertThat(task.excludeTags).containsExactly("debug-exclude-tag") } + { assertThat(task.includeTags.get()).containsExactly("global-include-tag") }, + { assertThat(task.excludeTags.get()).containsExactly("debug-exclude-tag") } ) }, @@ -99,15 +99,15 @@ interface AgpInstrumentationSupportTests : AgpVariantAwareTests { dynamicTest("has a task for writing the freeDebug filters DSL to a resource file") { val task = project.tasks.get("writeFiltersFreeDebugAndroidTest") assertThat(task).isNotNull() - assertThat(task.includeTags).containsExactly("global-include-tag", "freeDebug-include-tag") - assertThat(task.excludeTags).containsExactly("global-exclude-tag") + assertThat(task.includeTags.get()).containsExactly("global-include-tag", "freeDebug-include-tag") + assertThat(task.excludeTags.get()).containsExactly("global-exclude-tag") }, dynamicTest("has a task for writing the paidDebug filters DSL to a resource file") { val task = project.tasks.get("writeFiltersPaidDebugAndroidTest") assertThat(task).isNotNull() - assertThat(task.includeTags).containsExactly("global-include-tag") - assertThat(task.excludeTags).containsExactly("global-exclude-tag") + assertThat(task.includeTags.get()).containsExactly("global-include-tag") + assertThat(task.excludeTags.get()).containsExactly("global-exclude-tag") }, dynamicTest("doesn't have tasks for writing the release filters DSL to a resource file") { diff --git a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/plugin/InstrumentationSupportTests.kt b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/plugin/InstrumentationSupportTests.kt index 3baaa072..b5713867 100644 --- a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/plugin/InstrumentationSupportTests.kt +++ b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/plugin/InstrumentationSupportTests.kt @@ -165,6 +165,16 @@ class InstrumentationSupportTests { assertThat(project).configuration("androidTestRuntimeOnly").hasDependency(runnerLibrary()) } + @Test + fun `register the filter-write tasks`() { + project.addJUnitJupiterApi() + project.evaluate() + + // AGP only registers androidTest tasks for the debug build type + assertThat(project).task("writeFiltersDebugAndroidTest").exists() + assertThat(project).task("writeFiltersReleaseAndroidTest").doesNotExist() + } + /* Private */ private fun Project.addJUnitJupiterApi() { diff --git a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFiltersTests.kt b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFiltersTests.kt new file mode 100644 index 00000000..d83cec29 --- /dev/null +++ b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/tasks/AndroidJUnit5WriteFiltersTests.kt @@ -0,0 +1,77 @@ +package de.mannodermaus.gradle.plugins.junit5.tasks + +import com.google.common.truth.Truth.assertThat +import de.mannodermaus.gradle.plugins.junit5.internal.config.INSTRUMENTATION_FILTER_RES_FILE_NAME +import de.mannodermaus.gradle.plugins.junit5.plugin.TestProjectProviderExtension +import de.mannodermaus.gradle.plugins.junit5.util.assertAll +import de.mannodermaus.gradle.plugins.junit5.util.evaluate +import org.gradle.api.Project +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.RegisterExtension +import java.io.File +import java.nio.file.Paths +import kotlin.io.path.readLines + +class AndroidJUnit5WriteFiltersTests { + @RegisterExtension + @JvmField + val projectExtension = TestProjectProviderExtension() + + private lateinit var project: Project + + @BeforeEach + fun beforeEach() { + project = projectExtension.newProject() + .asAndroidApplication() + .applyJUnit5Plugin(true) { junitPlatform -> + junitPlatform.filters().includeTags("included") + junitPlatform.filters().excludeTags("excluded", "another-group") + } + .build() + project.evaluate() + } + + @Test + fun `generates file structure correctly`() { + // Expect a 'raw' folder inside the output, then the actual filters file in that sub-folder + val output = project.runTaskAndGetOutputFolder() + + File(output, "raw").apply { + assertAll( + "output contains 'raw' folder", + { assertThat(exists()).isTrue() }, + { assertThat(isDirectory).isTrue() }, + ) + + File(this, INSTRUMENTATION_FILTER_RES_FILE_NAME).apply { + assertAll( + "'raw' folder contains filters file'", + { assertThat(exists()).isTrue() }, + { assertThat(isFile).isTrue() }, + ) + } + } + } + + @Test + fun `file contains expected content`() { + val output = project.runTaskAndGetOutputFolder() + val file = Paths.get(output.absolutePath, "raw", INSTRUMENTATION_FILTER_RES_FILE_NAME) + + val content = file.readLines() + assertThat(content).containsExactly( + "-t included", + "-T excluded", + "-T another-group", + ) + } + + /* Private */ + + private fun Project.runTaskAndGetOutputFolder(): File { + val task = project.tasks.getByName("writeFiltersDebugAndroidTest") as AndroidJUnit5WriteFilters + task.execute() + return requireNotNull(task.outputFolder.get().asFile) + } +} diff --git a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/util/GradleTruth.kt b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/util/GradleTruth.kt index f5742239..b51bfce7 100644 --- a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/util/GradleTruth.kt +++ b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/util/GradleTruth.kt @@ -3,8 +3,10 @@ package de.mannodermaus.gradle.plugins.junit5.util import com.google.common.truth.FailureMetadata import com.google.common.truth.Subject import com.google.common.truth.Truth +import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import org.gradle.api.Project +import org.gradle.api.Task import org.gradle.api.artifacts.Configuration /* Methods */ @@ -22,6 +24,10 @@ class ProjectSubject( fun configuration(name: String): ConfigurationSubject = check("configuration()") .about(::ConfigurationSubject) .that(actual?.configurations?.getByName(name)) + + fun task(name: String): TaskSubject = check("task()") + .about(::TaskSubject) + .that(actual?.tasks?.findByName(name)) } class ConfigurationSubject( @@ -66,3 +72,16 @@ class ConfigurationSubject( ).that(hasMatch).isEqualTo(expectExists) } } + +class TaskSubject( + metadata: FailureMetadata, + private val actual: Task?, +) : Subject(metadata, actual) { + fun exists() { + assertThat(actual).isNotNull() + } + + fun doesNotExist() { + assertThat(actual).isNull() + } +} diff --git a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/util/projects/PluginSpecProjectCreator.kt b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/util/projects/PluginSpecProjectCreator.kt index f847d168..57b89db0 100644 --- a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/util/projects/PluginSpecProjectCreator.kt +++ b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/util/projects/PluginSpecProjectCreator.kt @@ -1,6 +1,8 @@ package de.mannodermaus.gradle.plugins.junit5.util.projects +import de.mannodermaus.gradle.plugins.junit5.dsl.AndroidJUnitPlatformExtension import de.mannodermaus.gradle.plugins.junit5.internal.extensions.android +import de.mannodermaus.gradle.plugins.junit5.internal.extensions.junitPlatform import de.mannodermaus.gradle.plugins.junit5.util.TestEnvironment import de.mannodermaus.gradle.plugins.junit5.util.applyPlugin import de.mannodermaus.gradle.plugins.junit5.util.evaluate @@ -40,7 +42,7 @@ class PluginSpecProjectCreator(private val environment: TestEnvironment) { private var projectType = Type.Unset private var appId = "com.example.android" - private var applyJUnit5Plugin = true + private var applyJUnit5Plugin: ((AndroidJUnitPlatformExtension) -> Unit)? = {} private var applyJacocoPlugin = false private var applyKotlinPlugin = false @@ -60,8 +62,12 @@ class PluginSpecProjectCreator(private val environment: TestEnvironment) { fun asAndroidLibrary() = setProjectTypeIfUnsetTo(Type.Library) - fun applyJUnit5Plugin(state: Boolean = true) = apply { - this.applyJUnit5Plugin = state + fun applyJUnit5Plugin(state: Boolean = true, configuration: ((AndroidJUnitPlatformExtension) -> Unit)? = null) = apply { + this.applyJUnit5Plugin = if (state) { + configuration ?: {} + } else { + null + } } fun applyJacocoPlugin(state: Boolean = true) = apply { @@ -93,7 +99,7 @@ class PluginSpecProjectCreator(private val environment: TestEnvironment) { project.applyPlugin("kotlin-android") } - if (applyJUnit5Plugin) { + if (applyJUnit5Plugin != null) { project.applyPlugin("de.mannodermaus.android-junit5") } @@ -116,6 +122,14 @@ class PluginSpecProjectCreator(private val environment: TestEnvironment) { // swallow this particular error } + // Configure JUnit 5 with custom configuration clause, if any + try { + applyJUnit5Plugin?.invoke(project.junitPlatform) + } catch (e: UnknownDomainObjectException) { + // Expected when the JUnit 5 plugin is not applied to a project; + // swallow this particular error + } + return project }