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

Add --flaky-test-attempts #454

Merged
merged 6 commits into from
Jan 11, 2019
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ gcloud:
version: 11.2
locale: en
orientation: portrait
# The number of times to retry failed tests. Default is 0. Max is 10.
flaky-test-attempts: 0

flank:
# test shards - the amount of groups to split the test suite into
Expand Down Expand Up @@ -118,6 +120,8 @@ gcloud:
device:
- model: NexusLowRes
version: 28
# The number of times to retry failed tests. Default is 0. Max is 10.
flaky-test-attempts: 0

flank:
# test shards - the amount of groups to split the test suite into
Expand Down
1 change: 1 addition & 0 deletions release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Fix create Gcs bucket [#444](https://github.com/TestArmada/flank/pull/444)
- Add `files-to-download` to Android and iOS. Specify a list of regular expressions to download files from the Google Cloud Storage bucket. [#441](https://github.com/TestArmada/flank/pull/441)
- Add `flank auth login` to authorize with a user account instead of a service account. [#446](https://github.com/TestArmada/flank/pull/436)
- Add `flaky-test-attempts` support on Android and iOS which automatically retries failed tests. [#454](https://github.com/TestArmada/flank/pull/454)

## v4.1.1

Expand Down
Binary file added test_app/apks/flaky-androidTest.apk
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.app;

import android.Manifest;
import android.os.SystemClock;
import android.support.test.rule.GrantPermissionRule;
import android.support.test.runner.AndroidJUnit4;
import com.instructure.espresso.ScreenshotTestRule;
Expand All @@ -9,6 +10,7 @@
import org.junit.runner.RunWith;

import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.fail;

@RunWith(AndroidJUnit4.class)
public class ExampleUiTest {
Expand All @@ -30,4 +32,11 @@ public void testPasses() {
public void testFails() {
assertEquals(true, false);
}

@Test
public void testIsFlaky() {
if ((SystemClock.uptimeMillis() %2) == 0) {
fail();
}
}
}
2 changes: 2 additions & 0 deletions test_runner/flank.ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ gcloud:
version: 12.0
locale: en
orientation: portrait
# The number of times to retry failed tests. Default is 0. Max is 10.
flaky-test-attempts: 0

flank:
# # Google cloud storage path to store the JUnit XML results from the last run.
Expand Down
1 change: 1 addition & 0 deletions test_runner/flank.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ gcloud:
device:
- model: NexusLowRes
version: 28
flaky-test-attempts: 1 # default is 0

flank:
# # Google cloud storage path to store the JUnit XML results from the last run.
Expand Down
2 changes: 2 additions & 0 deletions test_runner/src/main/kotlin/ftl/args/AndroidArgs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class AndroidArgs(
override val async = cli?.async ?: gcloud.async
override val project = cli?.project ?: gcloud.project
override val resultsHistoryName = cli?.resultsHistoryName ?: gcloud.resultsHistoryName
override val flakyTestAttempts = cli?.flakyTestAttempts ?: gcloud.flakyTestAttempts

private val androidGcloud = androidGcloudYml.gcloud
var appApk = cli?.app ?: androidGcloud.app
Expand Down Expand Up @@ -155,6 +156,7 @@ ${listToString(directoriesToPull)}
${listToString(testTargets)}
device:
${devicesToString(devices)}
flaky-test-attempts: $flakyTestAttempts

flank:
testShards: $testShards
Expand Down
1 change: 1 addition & 0 deletions test_runner/src/main/kotlin/ftl/args/IArgs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface IArgs {
val async: Boolean
val project: String
val resultsHistoryName: String?
val flakyTestAttempts: Int

// FlankYml
val testShards: Int
Expand Down
2 changes: 2 additions & 0 deletions test_runner/src/main/kotlin/ftl/args/IosArgs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class IosArgs(
override val async = cli?.async ?: gcloud.async
override val project = cli?.project ?: gcloud.project
override val resultsHistoryName = cli?.resultsHistoryName ?: gcloud.resultsHistoryName
override val flakyTestAttempts = cli?.flakyTestAttempts ?: gcloud.flakyTestAttempts

private val iosGcloud = iosGcloudYml.gcloud
var xctestrunZip = cli?.test ?: iosGcloud.test
Expand Down Expand Up @@ -117,6 +118,7 @@ IosArgs
xcode-version: $xcodeVersion
device:
${devicesToString(devices)}
flaky-test-attempts: $flakyTestAttempts

flank:
testShards: $testShards
Expand Down
7 changes: 5 additions & 2 deletions test_runner/src/main/kotlin/ftl/args/yml/GcloudYml.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,14 @@ class GcloudYmlParams(
val project: String = getDefaultProjectId() ?: "",

@field:JsonProperty("results-history-name")
val resultsHistoryName: String? = null
val resultsHistoryName: String? = null,

@field:JsonProperty("flaky-test-attempts")
val flakyTestAttempts: Int = 0
) {
companion object : IYmlKeys {
override val keys =
listOf("results-bucket", "record-video", "timeout", "async", "project", "results-history-name", "results-dir")
listOf("results-bucket", "results-dir", "record-video", "timeout", "async", "project", "results-history-name", "flaky-test-attempts")
}

init {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,11 @@ class AndroidRunCommand : Runnable {
"intermingled."]
)
var resultsDir: String? = null

@Option(
names = ["--flaky-test-attempts"],
description = ["The number of times a TestExecution should be re-attempted if one or more of its test cases " +
"fail for any reason. The maximum number of reruns allowed is 10. Default is 0, which implies no reruns."]
)
var flakyTestAttempts: Int? = null
}
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,11 @@ class IosRunCommand : Runnable {
"intermingled."]
)
var resultsDir: String? = null

@Option(
names = ["--flaky-test-attempts"],
description = ["The number of times a TestExecution should be re-attempted if one or more of its test cases " +
"fail for any reason. The maximum number of reruns allowed is 10. Default is 0, which implies no reruns."]
)
var flakyTestAttempts: Int? = null
}
1 change: 1 addition & 0 deletions test_runner/src/main/kotlin/ftl/gc/GcAndroidTestMatrix.kt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ object GcAndroidTestMatrix {
.setTestSpecification(testSpecification)
.setResultStorage(resultsStorage)
.setEnvironmentMatrix(environmentMatrix)
.setFlakyTestAttempts(args.flakyTestAttempts)
try {
return GcTesting.get.projects().testMatrices().create(args.project, testMatrix)
} catch (e: Exception) {
Expand Down
1 change: 1 addition & 0 deletions test_runner/src/main/kotlin/ftl/gc/GcIosTestMatrix.kt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ object GcIosTestMatrix {
.setTestSpecification(testSpecification)
.setEnvironmentMatrix(environmentMatrix)
.setResultStorage(resultStorage)
.setFlakyTestAttempts(args.flakyTestAttempts)

try {
return GcTesting.get.projects().testMatrices().create(args.project, testMatrix)
Expand Down
5 changes: 5 additions & 0 deletions test_runner/src/main/kotlin/ftl/run/TestRunner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@ object TestRunner {
break
}

// flaky-test-attempts restarts progress array at size 1
if (lastProgressLen > progress.size) {
lastProgressLen = 0
}

// Progress contains all messages. only print new updates
for (msg in progress.listIterator(lastProgressLen)) {
puts(msg)
Expand Down
21 changes: 21 additions & 0 deletions test_runner/src/test/kotlin/ftl/args/AndroidArgsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class AndroidArgsTest {
version: 24
locale: en
orientation: portrait
flaky-test-attempts: 3

flank:
testShards: 7
Expand Down Expand Up @@ -153,6 +154,7 @@ class AndroidArgsTest {
Device("NexusLowRes", "24", "en", "portrait")
)
)
assert(flakyTestAttempts, 3)

// FlankYml
assert(testShards, 7)
Expand Down Expand Up @@ -205,6 +207,7 @@ AndroidArgs
version: 24
locale: en
orientation: portrait
flaky-test-attempts: 3

flank:
testShards: 7
Expand Down Expand Up @@ -248,6 +251,7 @@ AndroidArgs
assert(performanceMetrics, true)
assert(testTargets, empty)
assert(devices, listOf(Device("NexusLowRes", "28")))
assert(flakyTestAttempts, 0)

// FlankYml
assert(testShards, 1)
Expand Down Expand Up @@ -710,4 +714,21 @@ AndroidArgs
assertThat(AndroidArgs.load(yaml).resultsDir).isEqualTo("a")
assertThat(AndroidArgs.load(yaml, cli).resultsDir).isEqualTo("b")
}

@Test
fun cli_flakyTestAttempts() {
val cli = AndroidRunCommand()
CommandLine(cli).parse("--flaky-test-attempts=3")

val yaml = """
gcloud:
app: $appApk
test: $testApk
results-dir: a
"""
assertThat(AndroidArgs.load(yaml).flakyTestAttempts).isEqualTo(0)

val androidArgs = AndroidArgs.load(yaml, cli)
assertThat(androidArgs.flakyTestAttempts).isEqualTo(3)
}
}
2 changes: 1 addition & 1 deletion test_runner/src/test/kotlin/ftl/args/ArgsHelperTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ArgsHelperTest {
fun mergeYmlMaps_succeeds() {
val merged = mergeYmlMaps(GcloudYml, IosGcloudYml)
assertThat(merged.keys.size).isEqualTo(1)
assertThat(merged["gcloud"]?.size).isEqualTo(11)
assertThat(merged["gcloud"]?.size).isEqualTo(12)
}

@Test
Expand Down
21 changes: 21 additions & 0 deletions test_runner/src/test/kotlin/ftl/args/IosArgsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class IosArgsTest {
version: 11.2
locale: c
orientation: d
flaky-test-attempts: 4

flank:
testShards: 7
Expand Down Expand Up @@ -123,6 +124,8 @@ class IosArgsTest {

// IosFlankYml
assert(testTargets, listOf("b/testBasicSelection", "b/testBasicSelection2"))

assert(flakyTestAttempts, 4)
}
}

Expand Down Expand Up @@ -153,6 +156,7 @@ IosArgs
version: 11.2
locale: c
orientation: d
flaky-test-attempts: 4

flank:
testShards: 7
Expand Down Expand Up @@ -193,6 +197,7 @@ IosArgs
assert(xctestrunZip, testAbsolutePath)
assert(xctestrunFile, xctestrunFileAbsolutePath)
assert(devices, listOf(Device("iphone8", "12.0")))
assert(flakyTestAttempts, 0)

// FlankYml
assert(testShards, 1)
Expand Down Expand Up @@ -528,4 +533,20 @@ IosArgs
val androidArgs = IosArgs.load(yaml, cli)
assertThat(androidArgs.filesToDownload).isEqualTo(listOf("a", "b"))
}

@Test
fun cli_flakyTestAttempts() {
val cli = IosRunCommand()
CommandLine(cli).parse("--flaky-test-attempts=3")

val yaml = """
gcloud:
test: $testPath
xctestrun-file: $testPath
"""
assertThat(IosArgs.load(yaml).flakyTestAttempts).isEqualTo(0)

val androidArgs = IosArgs.load(yaml, cli)
assertThat(androidArgs.flakyTestAttempts).isEqualTo(3)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class AndroidRunCommandTest {
assertThat(cmd.testTargetsAlwaysRun).isNull()
assertThat(cmd.filesToDownload).isNull()
assertThat(cmd.resultsDir).isNull()
assertThat(cmd.flakyTestAttempts).isNull()
}

@Test
Expand Down Expand Up @@ -282,4 +283,12 @@ class AndroidRunCommandTest {

assertThat(cmd.filesToDownload).isEqualTo(arrayListOf("a", "b"))
}

@Test
fun flakyTestAttempts_parse() {
val cmd = AndroidRunCommand()
CommandLine(cmd).parse("--flaky-test-attempts=10")

assertThat(cmd.flakyTestAttempts).isEqualTo(10)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class IosRunCommandTest {
assertThat(cmd.xcodeVersion).isNull()
assertThat(cmd.device).isNull()
assertThat(cmd.resultsDir).isNull()
assertThat(cmd.flakyTestAttempts).isNull()
}

@Test
Expand Down Expand Up @@ -216,4 +217,12 @@ class IosRunCommandTest {

assertThat(cmd.filesToDownload).isEqualTo(arrayListOf("a", "b"))
}

@Test
fun flakyTestAttempts_parse() {
val cmd = IosRunCommand()
CommandLine(cmd).parse("--flaky-test-attempts=10")

assertThat(cmd.flakyTestAttempts).isEqualTo(10)
}
}