Skip to content

Commit de2336d

Browse files
committed
Pass test time estimate as stabilize smart flank without cached results
1 parent 4ac4ce3 commit de2336d

13 files changed

Lines changed: 111 additions & 6 deletions

File tree

test_runner/src/main/kotlin/ftl/args/AndroidArgs.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class AndroidArgs(
6464
private val flank = flankYml.flank
6565
override val maxTestShards = cli?.maxTestShards ?: flank.maxTestShards
6666
override val shardTime = cli?.shardTime ?: flank.shardTime
67+
override val testTimeEstimate = cli?.testTimeEstimate ?: flank.testTimeEstimate
6768
override val repeatTests = cli?.repeatTests ?: flank.repeatTests
6869
override val smartFlankGcsPath = cli?.smartFlankGcsPath ?: flank.smartFlankGcsPath
6970
override val smartFlankDisableUpload = cli?.smartFlankDisableUpload ?: flank.smartFlankDisableUpload
@@ -139,6 +140,7 @@ ${devicesToString(devices)}
139140
flank:
140141
max-test-shards: $maxTestShards
141142
shard-time: $shardTime
143+
test-time-estimate: $testTimeEstimate
142144
num-test-runs: $repeatTests
143145
smart-flank-gcs-path: $smartFlankGcsPath
144146
smart-flank-disable-upload: $smartFlankDisableUpload

test_runner/src/main/kotlin/ftl/args/IArgs.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ interface IArgs {
2020
// FlankYml
2121
val maxTestShards: Int
2222
val shardTime: Int
23+
val testTimeEstimate: Int
2324
val repeatTests: Int
2425
val smartFlankGcsPath: String
2526
val smartFlankDisableUpload: Boolean

test_runner/src/main/kotlin/ftl/args/IosArgs.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class IosArgs(
5252
private val flank = flankYml.flank
5353
override val maxTestShards = cli?.maxTestShards ?: flank.maxTestShards
5454
override val shardTime = cli?.shardTime ?: flank.shardTime
55+
override val testTimeEstimate = cli?.testTimeEstimate ?: flank.testTimeEstimate
5556
override val repeatTests = cli?.repeatTests ?: flank.repeatTests
5657
override val smartFlankGcsPath = cli?.smartFlankGcsPath ?: flank.smartFlankGcsPath
5758
override val smartFlankDisableUpload = cli?.smartFlankDisableUpload ?: flank.smartFlankDisableUpload
@@ -127,6 +128,7 @@ ${devicesToString(devices)}
127128
flank:
128129
max-test-shards: $maxTestShards
129130
shard-time: $shardTime
131+
test-time-estimate: $testTimeEstimate
130132
num-test-runs: $repeatTests
131133
smart-flank-gcs-path: $smartFlankGcsPath
132134
smart-flank-disable-upload: $smartFlankDisableUpload

test_runner/src/main/kotlin/ftl/args/yml/FlankYml.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ class FlankYmlParams(
1313
@field:JsonProperty("shard-time")
1414
val shardTime: Int = -1,
1515

16+
@field:JsonProperty("test-time-estimate")
17+
val testTimeEstimate: Int = 10,
18+
1619
@field:JsonProperty("num-test-runs")
1720
val repeatTests: Int = 1,
1821

@@ -38,8 +41,9 @@ class FlankYmlParams(
3841
) {
3942
companion object : IYmlKeys {
4043
override val keys = listOf(
41-
"max-test-shards", "shard-time", "num-test-runs", "smart-flank-gcs-path", "smart-flank-disable-upload",
42-
"disable-sharding", "test-targets-always-run", "files-to-download", "project", "local-result-dir"
44+
"max-test-shards", "shard-time", "test-time-estimate", "num-test-runs", "smart-flank-gcs-path",
45+
"smart-flank-disable-upload", "disable-sharding", "test-targets-always-run", "files-to-download",
46+
"project", "local-result-dir"
4347
)
4448

4549
const val defaultLocalResultDir = "results"

test_runner/src/main/kotlin/ftl/cli/firebase/test/android/AndroidRunCommand.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,12 @@ class AndroidRunCommand : Runnable {
276276
)
277277
var shardTime: Int? = null
278278

279+
@Option(
280+
names = ["--test-time-estimate"],
281+
description = ["The approximate time in seconds each test is assumed to run for. This is used to help group tests in shards with Smart Flank"]
282+
)
283+
var testTimeEstimate: Int? = null
284+
279285
@Option(
280286
names = ["--num-test-runs"],
281287
description = ["The amount of times to run the test executions."]

test_runner/src/main/kotlin/ftl/cli/firebase/test/ios/IosRunCommand.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ class IosRunCommand : Runnable {
198198
)
199199
var shardTime: Int? = null
200200

201+
@Option(
202+
names = ["--test-time-estimate"],
203+
description = ["The approximately time in seconds each test is assumed to run for. This is used to groups tests in shards with Smart Flank"]
204+
)
205+
var testTimeEstimate: Int? = null
206+
201207
@Option(
202208
names = ["--num-test-runs"],
203209
description = ["The amount of times to run the test executions."]

test_runner/src/main/kotlin/ftl/shard/Shard.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ object Shard {
6666
if (args.shardTime < -1 || args.shardTime == 0) fatalError("Invalid shard time ${args.shardTime}")
6767

6868
val junitMap = createJunitMap(oldTestResult, args)
69-
val testsTotalTime = testsToRun.sumByDouble { junitMap[it] ?: 10.0 }
69+
val testsTotalTime = testsToRun.sumByDouble { junitMap[it] ?: args.testTimeEstimate.toDouble() }
7070

7171
val shardsByTime = ceil(testsTotalTime / args.shardTime).toInt()
7272

@@ -102,9 +102,11 @@ object Shard {
102102
var cacheMiss = 0
103103
val testcases = mutableListOf<TestMethod>()
104104

105+
// Set this arg to a local variable to avoid referencing it from args for every test.
106+
val testTimeEstimate = args.testTimeEstimate.toDouble()
105107
testsToRun.forEach { key ->
106108
val previousTime = junitMap[key]
107-
val time = previousTime ?: 10.0
109+
val time = previousTime ?: testTimeEstimate
108110

109111
if (previousTime == null) {
110112
cacheMiss += 1

test_runner/src/test/kotlin/ftl/args/AndroidArgsTest.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class AndroidArgsTest {
6464
flank:
6565
max-test-shards: 7
6666
shard-time: 60
67+
test-time-estimate: 50
6768
num-test-runs: 8
6869
files-to-download:
6970
- /sdcard/screenshots
@@ -185,6 +186,7 @@ class AndroidArgsTest {
185186
// FlankYml
186187
assert(maxTestShards, 7)
187188
assert(shardTime, 60)
189+
assert(testTimeEstimate, 50)
188190
assert(repeatTests, 8)
189191
assert(filesToDownload, listOf("/sdcard/screenshots", "/sdcard/screenshots2"))
190192
assert(
@@ -237,6 +239,7 @@ AndroidArgs
237239
flank:
238240
max-test-shards: 7
239241
shard-time: 60
242+
test-time-estimate: 50
240243
num-test-runs: 8
241244
smart-flank-gcs-path:${' '}
242245
smart-flank-disable-upload: false
@@ -291,6 +294,8 @@ AndroidArgs
291294

292295
// FlankYml
293296
assert(maxTestShards, 1)
297+
assert(shardTime, -1)
298+
assert(testTimeEstimate, 10)
294299
assert(repeatTests, 1)
295300
assert(filesToDownload, empty)
296301
assert(testTargetsAlwaysRun, empty)
@@ -765,6 +770,23 @@ AndroidArgs
765770
assertThat(AndroidArgs.load(yaml, cli).shardTime).isEqualTo(3)
766771
}
767772

773+
@Test
774+
fun `cli testTimeEstimate`() {
775+
val cli = AndroidRunCommand()
776+
CommandLine(cli).parseArgs("--test-time-estimate=30")
777+
778+
val yaml = """
779+
gcloud:
780+
app: $appApk
781+
test: $testApk
782+
783+
flank:
784+
test-time-estimate: 60
785+
"""
786+
assertThat(AndroidArgs.load(yaml).shardTime).isEqualTo(60)
787+
assertThat(AndroidArgs.load(yaml, cli).shardTime).isEqualTo(30)
788+
}
789+
768790
@Test
769791
fun `cli disableSharding`() {
770792
val cli = AndroidRunCommand()

test_runner/src/test/kotlin/ftl/args/FlankYmlTest.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ class FlankYmlTest {
2525
fun testValidArgs() {
2626
FlankYml()
2727
FlankYml(FlankYmlParams(maxTestShards = -1))
28-
val yml = FlankYml(FlankYmlParams(maxTestShards = 1, repeatTests = 1, shardTime = 58))
28+
val yml = FlankYml(FlankYmlParams(maxTestShards = 1, repeatTests = 1, shardTime = 58, testTimeEstimate = 60))
2929
assertThat(yml.flank.repeatTests).isEqualTo(1)
3030
assertThat(yml.flank.maxTestShards).isEqualTo(1)
3131
assertThat(yml.flank.shardTime).isEqualTo(58)
32+
assertThat(yml.flank.testTimeEstimate).isEqualTo(60)
3233
assertThat(yml.flank.testTargetsAlwaysRun).isEqualTo(emptyList<String>())
3334
assertThat(FlankYml.map).isNotEmpty()
3435
}

test_runner/src/test/kotlin/ftl/args/IosArgsTest.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class IosArgsTest {
5858
flank:
5959
max-test-shards: 7
6060
shard-time: 60
61+
test-time-estimate: 50
6162
num-test-runs: 8
6263
files-to-download:
6364
- /sdcard/screenshots
@@ -142,6 +143,7 @@ flank:
142143
// FlankYml
143144
assert(maxTestShards, 7)
144145
assert(shardTime, 60)
146+
assert(testTimeEstimate, 50)
145147
assert(repeatTests, 8)
146148
assert(testTargetsAlwaysRun, listOf("a/testGrantPermissions", "a/testGrantPermissions2"))
147149

@@ -184,6 +186,7 @@ IosArgs
184186
flank:
185187
max-test-shards: 7
186188
shard-time: 60
189+
test-time-estimate: 50
187190
num-test-runs: 8
188191
smart-flank-gcs-path:${' '}
189192
smart-flank-disable-upload: false
@@ -230,6 +233,7 @@ IosArgs
230233
// FlankYml
231234
assert(maxTestShards, 1)
232235
assert(shardTime, -1)
236+
assert(testTimeEstimate, 10)
233237
assert(repeatTests, 1)
234238
assert(testTargetsAlwaysRun, emptyList<String>())
235239
assert(filesToDownload, emptyList<String>())
@@ -445,6 +449,23 @@ IosArgs
445449
assertThat(IosArgs.load(yaml, cli).shardTime).isEqualTo(3)
446450
}
447451

452+
@Test
453+
fun `cli testTimeEstimate`() {
454+
val cli = IosRunCommand()
455+
CommandLine(cli).parseArgs("--test-time-estimate=30")
456+
457+
val yaml = """
458+
gcloud:
459+
test: $testPath
460+
xctestrun-file: $xctestrunFile
461+
462+
flank:
463+
test-time-estimate: 60
464+
"""
465+
assertThat(IosArgs.load(yaml).shardTime).isEqualTo(60)
466+
assertThat(IosArgs.load(yaml, cli).shardTime).isEqualTo(30)
467+
}
468+
448469
@Test
449470
fun `cli disableSharding`() {
450471
val cli = IosRunCommand()

0 commit comments

Comments
 (0)