Repository: runningcode/fladle (kotlin)

Issue:
Instrumentation APK should not be required if roboscript is specified.
We should require that either the instrumentation APK is specified or the robo script. Right now fladle requires that the instrumentation APK is always set meaning that roboscript cannot be used.

Thanks @digitalbuddha for reporting.

Pull request description:
Either must be specified but not both.

Fixes #128

Patch:
diff --git a/buildSrc/src/main/java/com/osacky/flank/gradle/FladlePluginDelegate.kt b/buildSrc/src/main/java/com/osacky/flank/gradle/FladlePluginDelegate.kt
index 2d62cf65..ca1ef0cf 100644
--- a/buildSrc/src/main/java/com/osacky/flank/gradle/FladlePluginDelegate.kt
+++ b/buildSrc/src/main/java/com/osacky/flank/gradle/FladlePluginDelegate.kt
@@ -107,8 +107,6 @@ class FladlePluginDelegate {
     if (base.serviceAccountCredentials.isPresent) {
       check(project.file(base.serviceAccountCredentials.get()).exists()) { "serviceAccountCredential file doesn't exist ${base.serviceAccountCredentials.get()}" }
     }
-    check(base.debugApk.isPresent) { "debugApk file must be specified ${base.debugApk.orNull}" }
-    check(base.instrumentationApk.isPresent) { "instrumentationApk file must be specified ${base.instrumentationApk.orNull}" }
   }
 
   private fun automaticallyConfigureTestOrchestrator(project: Project, extension: FlankGradleExtension, androidExtension: AppExtension) {
diff --git a/buildSrc/src/main/java/com/osacky/flank/gradle/YamlWriter.kt b/buildSrc/src/main/java/com/osacky/flank/gradle/YamlWriter.kt
index 41495d65..304729d2 100644
--- a/buildSrc/src/main/java/com/osacky/flank/gradle/YamlWriter.kt
+++ b/buildSrc/src/main/java/com/osacky/flank/gradle/YamlWriter.kt
@@ -9,7 +9,11 @@ internal class YamlWriter {
       check(base.serviceAccountCredentials.isPresent) { "ServiceAccountCredentials in fladle extension not set. https://github.com/runningcode/fladle#serviceaccountcredentials" }
     }
     check(base.debugApk.isPresent) { "debugApk must be specified" }
-    check(base.instrumentationApk.isPresent) { "instrumentationApk must be specified" }
+    check(base.instrumentationApk.isPresent xor !base.roboScript.isNullOrBlank()) { """
+     Either instrumentationApk file or roboScript file must be specified but not both.
+     instrumentationApk=${base.instrumentationApk.orNull}
+     roboScript=${base.roboScript}
+    """.trimIndent() }
 
     val deviceString = createDeviceString(config.devices)
     val additionalProperties = writeAdditionalProperties(config)
diff --git a/docs/changelog.md b/docs/changelog.md
index 8eebabb6..b98b8ad0 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,5 +1,8 @@
 # Changelog
 
+## 0.10.1
+* [Fix] Allow for specifying roboScript without specifying instrumentationApk. Fixes [#128](https://github.com/runningcode/fladle/issues/128).
+
 ## 0.10.0
 
 * Allow for debugging using [--dump-shards](/fladle/faq/#debugging)
diff --git a/docs/configuration.md b/docs/configuration.md
index 00532483..34de4413 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -173,6 +173,7 @@ Optional, prefer to set [variant](/configuration#variant).
 This is a string representing the path to the app's instrumentaiton apk. 
 Supports wildcard characters. 
 Optional, prefer to set [variant](/configuration#variant).
+InstrumenationApk should not be set when using [roboScript](/configuration#roboscript).
 
 === "Groovy"
     ``` groovy


Test patch:
diff --git a/buildSrc/src/test/java/com/osacky/flank/gradle/YamlWriterTest.kt b/buildSrc/src/test/java/com/osacky/flank/gradle/YamlWriterTest.kt
index 3b88e160..41deec03 100644
--- a/buildSrc/src/test/java/com/osacky/flank/gradle/YamlWriterTest.kt
+++ b/buildSrc/src/test/java/com/osacky/flank/gradle/YamlWriterTest.kt
@@ -177,7 +177,7 @@ class YamlWriterTest {
   }
 
   @Test
-  fun verifyInstrumentationApkThrowsError() {
+  fun verifyNoInstrumentationApkThrowsError() {
     val extension = emptyExtension {
       serviceAccountCredentials.set(project.layout.projectDirectory.file("fake.json"))
       debugApk.set("path")
@@ -186,7 +186,31 @@ class YamlWriterTest {
       yamlWriter.createConfigProps(extension, extension)
       fail()
     } catch (expected: IllegalStateException) {
-      assertEquals("instrumentationApk must be specified", expected.message)
+      assertThat(expected).hasMessageThat().isEqualTo("""
+        Either instrumentationApk file or roboScript file must be specified but not both.
+        instrumentationApk=null
+        roboScript=null
+      """.trimIndent())
+    }
+  }
+
+  @Test
+  fun verifyInstrumentationApkAndRoboscriptThrowsError() {
+    val extension = emptyExtension {
+      serviceAccountCredentials.set(project.layout.projectDirectory.file("fake.json"))
+      debugApk.set("path")
+      instrumentationApk.set("build/test/*.apk")
+      roboScript = "foo"
+    }
+    try {
+      yamlWriter.createConfigProps(extension, extension)
+      fail()
+    } catch (expected: IllegalStateException) {
+      assertThat(expected).hasMessageThat().isEqualTo("""
+        Either instrumentationApk file or roboScript file must be specified but not both.
+        instrumentationApk=build/test/*.apk
+        roboScript=foo
+      """.trimIndent())
     }
   }
 
diff --git a/buildSrc/src/test/java/com/osacky/flank/gradle/integration/FlankGradlePluginIntegrationTest.kt b/buildSrc/src/test/java/com/osacky/flank/gradle/integration/FlankGradlePluginIntegrationTest.kt
index c7e8d2ac..3c653653 100644
--- a/buildSrc/src/test/java/com/osacky/flank/gradle/integration/FlankGradlePluginIntegrationTest.kt
+++ b/buildSrc/src/test/java/com/osacky/flank/gradle/integration/FlankGradlePluginIntegrationTest.kt
@@ -2,7 +2,6 @@ package com.osacky.flank.gradle.integration
 
 import com.google.common.truth.Truth.assertThat
 import org.gradle.testkit.runner.GradleRunner
-import org.gradle.testkit.runner.UnexpectedBuildFailure
 import org.junit.Rule
 import org.junit.Test
 import org.junit.rules.TemporaryFolder
@@ -117,16 +116,58 @@ class FlankGradlePluginIntegrationTest {
              |}
              |""".trimMargin()
     )
-    try {
-
-      GradleRunner.create()
-          .withProjectDir(testProjectRoot.root)
-          .withPluginClasspath()
-          .withGradleVersion(minSupportGradleVersion)
-          .withArguments("printYml")
-          .build()
-    } catch (expected: UnexpectedBuildFailure) {
-      assertThat(expected).hasMessageThat().contains("debugApk must be specified")
-    }
+    val result = GradleRunner.create()
+        .withProjectDir(testProjectRoot.root)
+        .withPluginClasspath()
+        .withGradleVersion(minSupportGradleVersion)
+        .withArguments("runFlank")
+        .buildAndFail()
+    assertThat(result.output).contains("debugApk must be specified")
+  }
+
+  @Test
+  fun testMissingInstrumentationApkFailsBuild() {
+    writeBuildGradle(
+        """plugins {
+            id "com.osacky.fladle"
+           }
+           fladle {
+             serviceAccountCredentials = project.layout.projectDirectory.file("foo")
+             debugApk = "test-debug.apk"
+           }
+           """.trimIndent()
+    )
+    val result = GradleRunner.create()
+        .withProjectDir(testProjectRoot.root)
+        .withPluginClasspath()
+        .withGradleVersion(minSupportGradleVersion)
+        .withArguments("runFlank")
+        .buildAndFail()
+
+    assertThat(result.output).contains("Either instrumentationApk file or roboScript file must be specified but not both.")
+  }
+
+  @Test
+  fun testSpecifyingBothInstrumenationAndRoboscriptFailsBuild() {
+    writeBuildGradle(
+        """plugins {
+            id "com.osacky.fladle"
+           }
+           fladle {
+             serviceAccountCredentials = project.layout.projectDirectory.file("foo")
+             debugApk = "test-debug.apk"
+             instrumentationApk = "instrumenation-debug.apk"
+             roboScript = "foo.script"
+           }
+           """.trimIndent()
+    )
+    val result = GradleRunner.create()
+        .withProjectDir(testProjectRoot.root)
+        .withPluginClasspath()
+        .withGradleVersion(minSupportGradleVersion)
+        .withArguments("printYml")
+        .buildAndFail()
+
+    assertThat(result.output).contains("Either instrumentationApk file or roboScript file must be specified but not both.")
   }
 }