Skip to content

Commit 7796d4c

Browse files
committed
Simplify & shrink
1 parent bb1ad60 commit 7796d4c

3 files changed

Lines changed: 31 additions & 55 deletions

File tree

test_app/bash/test_filters.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ function filter_annotation_method_foo {
3939
# should exclude both
4040
function filter_notPackage_foo_notClass_bar {
4141
run_instrument -e notPackage ${PACKAGE_FOO} -e notClass ${CLASS_BAR}
42-
}
42+
}

test_runner/src/main/kotlin/ftl/run/platform/android/CreateAndroidTestContext.kt

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ package ftl.run.platform.android
22

33
import com.linkedin.dex.parser.DecodedValue
44
import com.linkedin.dex.parser.DexParser
5+
import com.linkedin.dex.parser.TestAnnotation
6+
import com.linkedin.dex.parser.TestMethod
57
import com.linkedin.dex.parser.formatClassName
68
import com.linkedin.dex.parser.getAnnotationsDirectory
79
import com.linkedin.dex.parser.getClassAnnotationValues
8-
import com.linkedin.dex.spec.AnnotationsDirectoryItem
10+
import com.linkedin.dex.spec.ClassDefItem
911
import com.linkedin.dex.spec.DexFile
1012
import ftl.args.AndroidArgs
1113
import ftl.args.ArgsHelper
@@ -56,48 +58,37 @@ private fun InstrumentationTestContext.calculateShards(
5658

5759
private fun InstrumentationTestContext.getFlankTestMethods(
5860
testFilter: TestFilter
59-
): List<FlankTestMethod> {
60-
val parameterizedClasses = getParametrizedClasses()
61-
return getNonParametrizedClassesTests(testFilter, parameterizedClasses) + parameterizedClasses.toFlankTestMethods()
62-
}
61+
): List<FlankTestMethod> =
62+
getParametrizedClasses().let { parameterizedClasses: List<String> ->
63+
DexParser.findTestMethods(test.local).asSequence()
64+
.distinct()
65+
.filter(testFilter.shouldRun)
66+
.filterNot(parameterizedClasses::belong)
67+
.map(TestMethod::toFlankTestMethod).toList()
68+
.plus(parameterizedClasses.map(String::toFlankTestMethod))
69+
}
6370

64-
private fun InstrumentationTestContext.getParametrizedClasses() =
65-
DexParser.readDexFiles(test.local)
66-
.fold(mutableListOf<String>()) { parameterizedClasses, file ->
67-
file.classDefs.forEach { classDef ->
68-
val directory = file.getAnnotationsDirectory(classDef)
69-
if (file.hasRunWithAnnotation(directory) && file.isAnnotationParameterIsParametrized(directory)) {
70-
parameterizedClasses += file.formatClassName(classDef).dropLast(1)
71-
}
72-
}
73-
parameterizedClasses
74-
}
71+
private fun List<String>.belong(method: TestMethod) = any { className -> method.testName.startsWith(className) }
7572

76-
private fun DexFile.hasRunWithAnnotation(directory: AnnotationsDirectoryItem?) =
77-
getClassAnnotationValues(directory).map { it.name }.any { it.toLowerCase().contains("RunWith".toLowerCase()) }
73+
private fun TestMethod.toFlankTestMethod() = FlankTestMethod("class $testName", ignored = annotations.any { it.name == "org.junit.Ignore" })
7874

79-
private fun DexFile.isAnnotationParameterIsParametrized(directory: AnnotationsDirectoryItem?) =
80-
getClassAnnotationValues(directory)
81-
.flatMap { annotations -> annotations.values.values }
82-
.filterIsInstance<DecodedValue.DecodedType>()
83-
.map { it.value }
84-
.any { it.toLowerCase().contains("Parameterized".toLowerCase()) }
75+
private fun String.toFlankTestMethod() = FlankTestMethod("class $this", ignored = false)
8576

86-
private fun InstrumentationTestContext.getNonParametrizedClassesTests(
87-
testFilter: TestFilter,
88-
parameterizedClasses: List<String>
89-
) = DexParser.findTestMethods(test.local).asSequence()
90-
.distinct()
91-
.filter(testFilter.shouldRun)
92-
.filter { method -> parameterizedClasses.none { method.testName.contains(it) } }
93-
.map { testMethod ->
94-
FlankTestMethod(
95-
testName = "class ${testMethod.testName}",
96-
ignored = testMethod.annotations.any { it.name == "org.junit.Ignore" }
97-
)
98-
}.toList()
77+
private fun InstrumentationTestContext.getParametrizedClasses(): List<String> =
78+
DexParser.readDexFiles(test.local).fold(emptyList()) { accumulator, file: DexFile ->
79+
accumulator + file.classDefs
80+
.filter(file::isParametrizedClass)
81+
.map(file::formatClassName) // returns class name + '#'
82+
.map { it.dropLast(1) } // so drop '#'
83+
}
9984

100-
private fun List<String>.toFlankTestMethods() = map { FlankTestMethod("class $it", false) }
85+
private fun DexFile.isParametrizedClass(classDef: ClassDefItem): Boolean =
86+
getClassAnnotationValues(getAnnotationsDirectory(classDef)).let { annotations: List<TestAnnotation> ->
87+
annotations.any { it.name.contains("RunWith", ignoreCase = true) } && annotations
88+
.flatMap { it.values.values }
89+
.filterIsInstance<DecodedValue.DecodedType>()
90+
.any { it.value.contains("Parameterized", ignoreCase = true) }
91+
}
10192

10293
private fun List<AndroidTestContext>.dropEmptyInstrumentationTest(): List<AndroidTestContext> =
10394
filterIsInstance<InstrumentationTestContext>().filter { it.shards.isEmpty() }.let { withoutTests ->

test_runner/src/test/kotlin/ftl/run/platform/android/CreateAndroidTestContextKtTest.kt

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import ftl.run.model.RoboTestContext
77
import ftl.test.util.mixedConfigYaml
88
import ftl.test.util.should
99
import kotlinx.coroutines.runBlocking
10-
import org.junit.Assert
1110
import org.junit.Assert.assertEquals
1211
import org.junit.Test
1312

@@ -32,7 +31,7 @@ class CreateAndroidTestContextKtTest {
3231
app = should { local.endsWith("app-debug.apk") },
3332
test = should { local.endsWith("app-multiple-flaky-debug-androidTest.apk") },
3433
shards = listOf(
35-
should { size == 3 },
34+
should { size == 3 && contains("class com.example.test_app.ParameterizedTest") },
3635
should { size == 3 }
3736
)
3837
)
@@ -46,18 +45,4 @@ class CreateAndroidTestContextKtTest {
4645
// then
4746
assertEquals(expected, actual)
4847
}
49-
50-
@Test
51-
fun `should contains parametrized test`() {
52-
// given
53-
val expected = "class com.example.test_app.ParameterizedTest"
54-
55-
// when
56-
val actual = runBlocking {
57-
AndroidArgs.load(mixedConfigYaml).createAndroidTestContexts()
58-
}.map { it as? InstrumentationTestContext }.filterNotNull().flatMap { it.shards.flatten() }
59-
60-
// then
61-
Assert.assertTrue(actual.contains(expected))
62-
}
6348
}

0 commit comments

Comments
 (0)