Skip to content

Commit

Permalink
Adds new variant tests and configures dependency per variant.
Browse files Browse the repository at this point in the history
Fixes #233
  • Loading branch information
runningcode committed Apr 2, 2021
1 parent aec03bd commit 71a5e39
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ interface FladleConfig {
@get:Input
val flakyTestAttempts: Property<Int>

// Variant to use for configuring output APK.
@get:Input
@get:Optional
val variant: Property<String>

@get:Input
@get:Optional
val resultsBucket: Property<String>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ data class FladleConfigImpl(
override val smartFlankGcsPath: Property<String>,
override val resultsHistoryName: Property<String>,
override val flakyTestAttempts: Property<Int>,
override val variant: Property<String>,
override val directoriesToPull: ListProperty<String>,
override val filesToDownload: ListProperty<String>,
override val environmentVariables: MapProperty<String, String>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,6 @@ class FladlePluginDelegate {
// Must be done afterEvaluate otherwise extension values will not be set.
project.dependencies.add(FLADLE_CONFIG, "${base.flankCoordinates.get()}:${base.flankVersion.get()}")

// Only use automatic apk path detection for 'com.android.application' projects.
project.pluginManager.withPlugin("com.android.application") {
if (!base.debugApk.isPresent || !base.instrumentationApk.isPresent) {
findDebugAndInstrumentationApk(project, base)
}
}
tasks.apply {
createTasksForConfig(base, base, project, "")

Expand All @@ -69,6 +63,14 @@ class FladlePluginDelegate {
}

private fun TaskContainer.createTasksForConfig(base: FlankGradleExtension, config: FladleConfig, project: Project, name: String) {
// Only use automatic apk path detection for 'com.android.application' projects.
project.pluginManager.withPlugin("com.android.application") {
// This doesn't work properly for multiple configs since they likely are inheriting the config from root already.
if (!config.debugApk.isPresent || !config.instrumentationApk.isPresent) {
findDebugAndInstrumentationApk(project, config)
}
}

checkIfSanityAndValidateConfigs(config)
validateOptionsUsed(config = config, flank = base.flankVersion.get())
checkForExclusionUsage(config)
Expand Down Expand Up @@ -111,7 +113,7 @@ class FladlePluginDelegate {
if (config.dependOnAssemble.isPresent && config.dependOnAssemble.get()) {
val testedExtension = requireNotNull(project.extensions.findByType(TestedExtension::class.java)) { "Could not find TestedExtension in ${project.name}" }
testedExtension.testVariants.configureEach {
if (base.isExpectedVariant(testedVariant)) {
if (config.isExpectedVariant(testedVariant)) {
if (testedVariant.assembleProvider.isPresent) {
dependsOn(testedVariant.assembleProvider)
}
Expand All @@ -128,42 +130,42 @@ class FladlePluginDelegate {
}
}

private fun automaticallyConfigureTestOrchestrator(project: Project, extension: FlankGradleExtension, androidExtension: AppExtension) {
private fun automaticallyConfigureTestOrchestrator(project: Project, config: FladleConfig, androidExtension: AppExtension) {
project.afterEvaluate {
val useOrchestrator = androidExtension.testOptions.executionEnum == TestOptions.Execution.ANDROIDX_TEST_ORCHESTRATOR || androidExtension.testOptions.executionEnum == TestOptions.Execution.ANDROID_TEST_ORCHESTRATOR
if (useOrchestrator) {
log("Automatically detected the use of Android Test Orchestrator")
}
extension.useOrchestrator.set(useOrchestrator)
config.useOrchestrator.set(useOrchestrator)
}
}

private fun findDebugAndInstrumentationApk(project: Project, extension: FlankGradleExtension) {
private fun findDebugAndInstrumentationApk(project: Project, config: FladleConfig) {
val baseExtension = requireNotNull(project.extensions.findByType(AppExtension::class.java)) { "Could not find AppExtension in ${project.name}" }
automaticallyConfigureTestOrchestrator(project, extension, baseExtension)
automaticallyConfigureTestOrchestrator(project, config, baseExtension)
baseExtension.testVariants.configureEach {
val appVariant = testedVariant
outputs.configureEach test@{
appVariant.outputs.configureEach app@{
if (extension.isExpectedVariant(appVariant)) {
if (config.isExpectedVariant(appVariant)) {

if (!extension.debugApk.isPresent) {
if (!config.debugApk.isPresent) {
// Don't set debug apk if not already set. #172
project.log("Configuring fladle.debugApk from variant ${this@app.name}")
extension.debugApk.set(this@app.outputFile.absolutePath)
config.debugApk.set(this@app.outputFile.absolutePath)
}
if (!extension.roboScript.isPresent && !extension.instrumentationApk.isPresent && !extension.sanityRobo.get()) {
if (!config.roboScript.isPresent && !config.instrumentationApk.isPresent && !config.sanityRobo.get()) {
// Don't set instrumentation apk if not already set. #172
project.log("Configuring fladle.instrumentationApk from variant ${this@test.name}")
extension.instrumentationApk.set(this@test.outputFile.absolutePath)
config.instrumentationApk.set(this@test.outputFile.absolutePath)
}
}
}
}
}
}

private fun FlankGradleExtension.isExpectedVariant(
private fun FladleConfig.isExpectedVariant(
appVariant: BaseVariant
) = !variant.isPresent || (variant.isPresent && variant.get() == appVariant.name)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ open class FlankGradleExtension @Inject constructor(objects: ObjectFactory) : Fl

override val flakyTestAttempts: Property<Int> = objects.property<Int>().convention(0)

// Variant to use for configuring output APK.
@get:Input
@get:Optional
val variant: Property<String> = objects.property()
override val variant: Property<String> = objects.property()

/**
* debugApk and instrumentationApk are [Property<String>] and not [RegularFileProperty] because we support wildcard characters.
Expand Down Expand Up @@ -169,6 +166,7 @@ open class FlankGradleExtension @Inject constructor(objects: ObjectFactory) : Fl
smartFlankGcsPath = objects.property<String>().convention(smartFlankGcsPath),
resultsHistoryName = objects.property<String>().convention(resultsHistoryName),
flakyTestAttempts = objects.property<Int>().convention(flakyTestAttempts),
variant = objects.property<String>().convention(variant),
directoriesToPull = objects.listProperty<String>().convention(directoriesToPull),
filesToDownload = objects.listProperty<String>().convention(filesToDownload),
environmentVariables = objects.mapProperty<String, String>().convention(environmentVariables),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,40 +128,6 @@ class FlankGradlePluginIntegrationTest {
assertThat(result.output).contains("debugApk must be specified")
}

@Test
fun testWithDependOnAssembleNoFlavors() {
val result = setUpDependOnAssemble(true, withFlavors = false)
assertThat(result.output).contains(":assembleDebug")
assertThat(result.output).contains(":assembleDebugAndroidTest")
assertThat(result.output).doesNotContain(":assembleRelease")
}

@Test
fun testWithOutDependOnAssembleNoFlavors() {
val result = setUpDependOnAssemble(false, withFlavors = false)
assertThat(result.output).doesNotContain(":assembleDebug")
assertThat(result.output).doesNotContain(":assembleDebugAndroidTest")
assertThat(result.output).doesNotContain(":assembleRelease")
}

@Test
fun testWithDependOnAssembleAndFlavors() {
val result = setUpDependOnAssemble(true, withFlavors = true)
assertThat(result.output).contains(":assembleChocolateDebug")
assertThat(result.output).contains(":assembleChocolateDebugAndroidTest")
assertThat(result.output).doesNotContain(":assembleChocolateRelease")
assertThat(result.output).doesNotContain(":assembleVanilla")
}

@Test
fun testWithOutDependOnAssembleAndFlavors() {
val result = setUpDependOnAssemble(false, withFlavors = true)
assertThat(result.output).doesNotMatch(":assemble.*")
assertThat(result.output).doesNotContain(":assembleChocolateDebug")
assertThat(result.output).doesNotContain(":assembleDebug")
assertThat(result.output).doesNotContain(":assembleRelease")
assertThat(result.output).doesNotContain(":assembleDebugAndroidTest")
}

@Test
fun testMissingInstrumentationApkFailsBuild() {
Expand Down Expand Up @@ -200,7 +166,7 @@ class FlankGradlePluginIntegrationTest {
}
""".trimIndent()
)
testProjectRoot.newFile("foo").writeText("{}")
testProjectRoot.writeEmptyServiceCredential()
val result = testProjectRoot.gradleRunner()
.withGradleVersion(minSupportGradleVersion)
.withArguments("printYml")
Expand Down Expand Up @@ -233,56 +199,4 @@ class FlankGradlePluginIntegrationTest {
.build()
assertThat(result.task(":printYmlFooConfig")!!.outcome).isEqualTo(TaskOutcome.SUCCESS)
}

private fun setUpDependOnAssemble(dependsOnAssemble: Boolean, withFlavors: Boolean = false): BuildResult {
testProjectRoot.setupFixture("android-project")
val flavors = if (withFlavors) {
"""
flavorDimensions "flavor"
productFlavors {
chocolate {
dimension "flavor"
}
vanilla {
dimension "flavor"
}
}
""".trimIndent()
} else { "" }
val variant = if (withFlavors) { """variant = "chocolateDebug"""" } else { "" }
writeBuildGradle(
"""plugins {
id "com.osacky.fladle"
id "com.android.application"
}
repositories {
google()
mavenCentral()
}
android {
compileSdkVersion 29
defaultConfig {
applicationId "com.osacky.flank.gradle.sample"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
$flavors
}
fladle {
serviceAccountCredentials = project.layout.projectDirectory.file("foo")
dependOnAssemble = $dependsOnAssemble
$variant
}
""".trimIndent()
)
return testProjectRoot.gradleRunner()
.withArguments("runFlank", "--dry-run")
.build()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ fun TemporaryFolder.gradleRunner() =
.withPluginClasspath()
.forwardOutput()
.withProjectDir(root)

fun TemporaryFolder.writeEmptyServiceCredential() {
newFile("foo").writeText("{}")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package com.osacky.flank.gradle.integration

import com.google.common.truth.Truth.assertThat
import org.gradle.testkit.runner.BuildResult
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder

class VariantTests {

@get:Rule
var testProjectRoot = TemporaryFolder()

@Test
fun testWithDependOnAssembleNoFlavors() {
val result = setUpDependOnAssemble(true, withFlavors = false)
assertThat(result.output).contains(":assembleDebug")
assertThat(result.output).contains(":assembleDebugAndroidTest")
assertThat(result.output).doesNotContain(":assembleRelease")
}

@Test
fun testWithOutDependOnAssembleNoFlavors() {
val result = setUpDependOnAssemble(false, withFlavors = false)
assertThat(result.output).doesNotContain(":assembleDebug")
assertThat(result.output).doesNotContain(":assembleDebugAndroidTest")
assertThat(result.output).doesNotContain(":assembleRelease")
}

@Test
fun testWithDependOnAssembleAndFlavors() {
val result = setUpDependOnAssemble(true, withFlavors = true)
assertThat(result.output).contains(":assembleChocolateDebug")
assertThat(result.output).contains(":assembleChocolateDebugAndroidTest")
assertThat(result.output).doesNotContain(":assembleChocolateRelease")
assertThat(result.output).doesNotContain(":assembleVanilla")
}

@Test
fun testWithOutDependOnAssembleAndFlavors() {
val result = setUpDependOnAssemble(false, withFlavors = true)
assertThat(result.output).doesNotMatch(":assemble.*")
assertThat(result.output).doesNotContain(":assembleChocolateDebug")
assertThat(result.output).doesNotContain(":assembleDebug")
assertThat(result.output).doesNotContain(":assembleRelease")
assertThat(result.output).doesNotContain(":assembleDebugAndroidTest")
}

@Test
fun testAdditionalFladleConfigForVariant() {
testProjectRoot.newFile("settings.gradle").writeText("rootProject.name = 'chocovanilla'")
val result = setUpDependOnAssemble(dependsOnAssemble = true, withFlavors = true, withFladleConfig = """
configs {
vanilla {
variant.set("vanillaDebug")
}
}
""".trimIndent(), withTask = "runFlankVanilla")
assertThat(result.output).contains(":assembleVanillaDebug")
assertThat(result.output).contains(":assembleVanillaDebugAndroidTest")
assertThat(result.output).doesNotContain(":assembleVanillaRelease")
assertThat(result.output).doesNotContain(":assembleChocolate")

testProjectRoot.writeEmptyServiceCredential()
val resultPrint = testProjectRoot.gradleRunner()
.withArguments("printYmlVanilla")
.build()

assertThat(resultPrint.output).contains("build/outputs/apk/vanilla/debug/chocovanilla-vanilla-debug.apk")
assertThat(resultPrint.output).contains("build/outputs/apk/androidTest/vanilla/debug/chocovanilla-vanilla-debug-androidTest.apk")
}

private fun setUpDependOnAssemble(dependsOnAssemble: Boolean, withFlavors: Boolean = false, withFladleConfig: String = "", withTask: String = "runFlank"): BuildResult {
testProjectRoot.setupFixture("android-project")
val flavors = if (withFlavors) {
"""
flavorDimensions "flavor"
productFlavors {
chocolate {
dimension "flavor"
}
vanilla {
dimension "flavor"
}
}
""".trimIndent()
} else { "" }
val variant = if (withFlavors) { """variant = "chocolateDebug"""" } else { "" }
writeBuildGradle(
"""plugins {
id "com.osacky.fladle"
id "com.android.application"
}
repositories {
google()
mavenCentral()
}
android {
compileSdkVersion 29
defaultConfig {
applicationId "com.osacky.flank.gradle.sample"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
$flavors
}
fladle {
serviceAccountCredentials = project.layout.projectDirectory.file("foo")
dependOnAssemble = $dependsOnAssemble
$variant
$withFladleConfig
}
""".trimIndent()
)
return testProjectRoot.gradleRunner()
.withArguments(withTask, "--dry-run")
.build()
}

fun writeBuildGradle(build: String) {
val file = testProjectRoot.newFile("build.gradle")
file.writeText(build)
}
}

0 comments on commit 71a5e39

Please sign in to comment.