Skip to content
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: Support for robo tests without robo script #1108

Merged
merged 5 commits into from
Sep 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions test_runner/src/main/kotlin/ftl/args/AndroidArgs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,20 @@ AndroidArgs
}

val AndroidArgs.isInstrumentationTest
get() = appApk != null && testApk != null ||
get() = appApk.isNotNull() &&
testApk.isNotNull() ||
additionalAppTestApks.isNotEmpty() &&
(appApk != null || additionalAppTestApks.all { (app, _) -> app != null })
(appApk.isNotNull() || additionalAppTestApks.all { (app, _) -> app.isNotNull() })

val AndroidArgs.isRoboTest
get() = appApk != null &&
(roboDirectives.isNotEmpty() || roboScript != null)
get() = appApk.isNotNull() &&
(roboDirectives.isNotEmpty() || roboScript.isNotNull())

val AndroidArgs.isSanityRobo
get() = appApk.isNotNull() &&
testApk.isNull() &&
roboScript.isNull() &&
additionalAppTestApks.isEmpty()

private fun String?.isNull() = this == null
private fun String?.isNotNull() = isNull().not()
4 changes: 1 addition & 3 deletions test_runner/src/main/kotlin/ftl/args/ValidateAndroidArgs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ private fun AndroidArgs.assertShards() {
}

private fun AndroidArgs.assertTestTypes() {
if (!(isRoboTest or isInstrumentationTest)) throw FlankConfigurationError(
"One of following options must be specified [test, robo-directives, robo-script]."
)
if (!(isRoboTest or isInstrumentationTest or isSanityRobo)) throw FlankConfigurationError("Unable to infer test type. Please check configuration")
}

// Validation is done according to https://cloud.google.com/sdk/gcloud/reference/firebase/test/android/run#--directories-to-pull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ data class RoboTestContext(
val app: FileReference,
val roboScript: FileReference
) : AndroidTestContext()

data class SanityRoboTestContext(
val app: FileReference
) : AndroidTestContext()
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import ftl.args.AndroidArgs
import ftl.run.model.AndroidTestContext
import ftl.run.model.InstrumentationTestContext
import ftl.run.model.RoboTestContext
import ftl.run.model.SanityRoboTestContext

internal fun AndroidArgs.createAndroidTestConfig(
testContext: AndroidTestContext
): AndroidTestConfig = when (testContext) {
is InstrumentationTestContext -> createInstrumentationConfig(testContext)
is RoboTestContext -> createRoboConfig(testContext)
is SanityRoboTestContext -> createSanityRoboConfig(testContext)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ftl.run.platform.android

import ftl.args.AndroidArgs
import ftl.run.model.RoboTestContext
import ftl.run.model.SanityRoboTestContext

internal fun AndroidArgs.createRoboConfig(
testApk: RoboTestContext
Expand All @@ -10,3 +11,11 @@ internal fun AndroidArgs.createRoboConfig(
flankRoboDirectives = roboDirectives,
roboScriptGcsPath = testApk.roboScript.gcs
)

internal fun createSanityRoboConfig(
testApk: SanityRoboTestContext
) = AndroidTestConfig.Robo(
appApkGcsPath = testApk.app.gcs,
flankRoboDirectives = null,
roboScriptGcsPath = null
)
45 changes: 23 additions & 22 deletions test_runner/src/main/kotlin/ftl/run/platform/android/ResolveApks.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,35 @@ package ftl.run.platform.android

import com.google.common.annotations.VisibleForTesting
import ftl.args.AndroidArgs
import ftl.args.isSanityRobo

import ftl.run.model.AndroidTestContext
import ftl.run.model.InstrumentationTestContext
import ftl.run.model.RoboTestContext
import ftl.run.exception.FlankGeneralError
import ftl.run.model.SanityRoboTestContext
import ftl.util.asFileReference

@VisibleForTesting
internal fun AndroidArgs.resolveApks(): List<AndroidTestContext> = listOfNotNull(
appApk?.let { appApk ->
testApk?.let { testApk ->
InstrumentationTestContext(
app = appApk.asFileReference(),
test = testApk.asFileReference()
)
} ?: roboScript?.let { roboScript ->
RoboTestContext(
app = appApk.asFileReference(),
roboScript = roboScript.asFileReference()
)
}
}
).plus(
elements = additionalAppTestApks.map {
InstrumentationTestContext(
app = (it.app ?: appApk)
?.asFileReference()
?: throw FlankGeneralError("Cannot create app-test apks pair for instrumentation tests, missing app apk for test ${it.test}"),
test = it.test.asFileReference()
)
}
mainApkContext(),
*additionalApksContexts()
)

private fun AndroidArgs.mainApkContext() = appApk?.let { appApk ->
when {
testApk != null -> InstrumentationTestContext(app = appApk.asFileReference(), test = testApk.asFileReference())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is a bit tricky because I want to take advantage of smart casting

roboScript != null -> RoboTestContext(app = appApk.asFileReference(), roboScript = roboScript.asFileReference())
isSanityRobo -> SanityRoboTestContext(app = appApk.asFileReference())
else -> null
}
}

private fun AndroidArgs.additionalApksContexts() = additionalAppTestApks.map {
InstrumentationTestContext(
app = (it.app ?: appApk)
?.asFileReference()
?: throw FlankGeneralError("Cannot create app-test apks pair for instrumentation tests, missing app apk for test ${it.test}"),
test = it.test.asFileReference()
)
}.toTypedArray()
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ftl.args.AndroidArgs
import ftl.run.model.AndroidTestContext
import ftl.run.model.InstrumentationTestContext
import ftl.run.model.RoboTestContext
import ftl.run.model.SanityRoboTestContext
import ftl.util.asFileReference
import ftl.util.uploadIfNeeded
import kotlinx.coroutines.Dispatchers
Expand All @@ -23,6 +24,7 @@ suspend fun List<AndroidTestContext>.upload(rootGcsBucket: String, runGcsPath: S
private fun AndroidTestContext.upload(rootGcsBucket: String, runGcsPath: String) = when (this) {
is InstrumentationTestContext -> upload(rootGcsBucket, runGcsPath)
is RoboTestContext -> upload(rootGcsBucket, runGcsPath)
is SanityRoboTestContext -> upload(rootGcsBucket, runGcsPath)
}

private fun InstrumentationTestContext.upload(rootGcsBucket: String, runGcsPath: String) = copy(
Expand All @@ -35,6 +37,8 @@ private fun RoboTestContext.upload(rootGcsBucket: String, runGcsPath: String) =
roboScript = roboScript.uploadIfNeeded(rootGcsBucket, runGcsPath)
)

private fun SanityRoboTestContext.upload(rootGcsBucket: String, runGcsPath: String) = SanityRoboTestContext(app.uploadIfNeeded(rootGcsBucket, runGcsPath))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line perhaps past the limit of line length? I wonder why detekt hasn't picked it up

Copy link
Contributor Author

@pawelpasterz pawelpasterz Sep 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know, there are even far longer lines and detekt doesn't complain about it ¯_(ツ)_/¯
I can verify its setting but prefer to do so in separate PR, lots of files could be affected

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets do it in another pull request.


suspend fun AndroidArgs.uploadAdditionalApks(runGcsPath: String) = coroutineScope {
additionalApks.map {
async { it.asFileReference().uploadIfNeeded(resultsBucket, runGcsPath).gcs }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,20 @@ import ftl.args.AndroidArgs
import ftl.args.yml.AppTestPair
import ftl.run.model.InstrumentationTestContext
import ftl.run.exception.FlankGeneralError
import ftl.run.model.SanityRoboTestContext
import ftl.util.asFileReference
import io.mockk.every
import io.mockk.mockk
import io.mockk.unmockkAll
import org.junit.After
import org.junit.Assert.assertArrayEquals
import org.junit.Test

class ResolveApksKtTest {

@After
fun tearDown() = unmockkAll()

@Test
fun `should resolve apks from global app and test`() {
assertArrayEquals(
Expand Down Expand Up @@ -67,4 +73,19 @@ class ResolveApksKtTest {
)
}.resolveApks()
}

@Test
fun `should return one sanity robo test context`() {
val androidArgs = mockk<AndroidArgs> {
every { appApk } returns "app"
every { testApk } returns null
every { additionalApks } returns emptyList()
every { additionalAppTestApks } returns emptyList()
every { roboScript } returns null
}
assertArrayEquals(
arrayOf(SanityRoboTestContext("app".asFileReference())),
androidArgs.resolveApks().toTypedArray()
)
}
}