Skip to content

Commit

Permalink
feat(configuration): move testClassRegex to parser configuration (#851)
Browse files Browse the repository at this point in the history
* feat(configuration): move testClassRegex to the only parser that needs it
  • Loading branch information
Malinskiy authored Oct 24, 2023
1 parent d140e93 commit a6c1281
Show file tree
Hide file tree
Showing 23 changed files with 62 additions and 95 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ iOS:
```yaml
name: "My application"
outputDir: "derived-data/Marathon"
testClassRegexes: ["^((?!Abstract).)*Tests$"]
vendorConfiguration:
type: "iOS"
bundle:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ data class Configuration private constructor(
val isCodeCoverageEnabled: Boolean,
val uncompletedTestRetryQuota: Int,

val testClassRegexes: Collection<Regex>,
val includeSerialRegexes: Collection<Regex>,
val excludeSerialRegexes: Collection<Regex>,

Expand Down Expand Up @@ -68,7 +67,6 @@ data class Configuration private constructor(
"ignoreFailures" to ignoreFailures.toString(),
"isCodeCoverageEnabled" to isCodeCoverageEnabled.toString(),
"executionStrategy" to executionStrategy.toString(),
"testClassRegexes" to testClassRegexes.toString(),
"includeSerialRegexes" to includeSerialRegexes.toString(),
"excludeSerialRegexes" to excludeSerialRegexes.toString(),
"testBatchTimeoutMillis" to testBatchTimeoutMillis.toString(),
Expand Down Expand Up @@ -100,8 +98,6 @@ data class Configuration private constructor(
if (isCodeCoverageEnabled != other.isCodeCoverageEnabled) return false
if (executionStrategy != other.executionStrategy) return false
if (uncompletedTestRetryQuota != other.uncompletedTestRetryQuota) return false
//For testing we need to compare configuration instances. Unfortunately Regex equality is broken so need to map it to String
if (testClassRegexes.map { it.pattern } != other.testClassRegexes.map { it.pattern }) return false
if (includeSerialRegexes.map { it.pattern } != other.includeSerialRegexes.map { it.pattern }) return false
if (excludeSerialRegexes.map { it.pattern } != other.excludeSerialRegexes.map { it.pattern }) return false
if (testBatchTimeoutMillis != other.testBatchTimeoutMillis) return false
Expand Down Expand Up @@ -132,7 +128,6 @@ data class Configuration private constructor(
result = 31 * result + isCodeCoverageEnabled.hashCode()
result = 31 * result + executionStrategy.hashCode()
result = 31 * result + uncompletedTestRetryQuota
result = 31 * result + testClassRegexes.hashCode()
result = 31 * result + includeSerialRegexes.hashCode()
result = 31 * result + excludeSerialRegexes.hashCode()
result = 31 * result + testBatchTimeoutMillis.hashCode()
Expand Down Expand Up @@ -163,7 +158,6 @@ data class Configuration private constructor(
var executionStrategy: ExecutionStrategyConfiguration = ExecutionStrategyConfiguration(),
var uncompletedTestRetryQuota: Int = Integer.MAX_VALUE,

var testClassRegexes: Collection<Regex> = listOf(Regex("^((?!Abstract).)*Test[s]*$")),
var includeSerialRegexes: Collection<Regex> = emptyList(),
var excludeSerialRegexes: Collection<Regex> = emptyList(),

Expand Down Expand Up @@ -197,7 +191,6 @@ data class Configuration private constructor(
isCodeCoverageEnabled = isCodeCoverageEnabled,
executionStrategy = executionStrategy,
uncompletedTestRetryQuota = uncompletedTestRetryQuota,
testClassRegexes = testClassRegexes,
includeSerialRegexes = includeSerialRegexes,
excludeSerialRegexes = excludeSerialRegexes,
testBatchTimeoutMillis = testBatchTimeoutMillis,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ sealed class VendorConfiguration {
@JsonProperty("compactOutput") val compactOutput: Boolean = false,
@JsonProperty("rsync") val rsync: RsyncConfiguration = RsyncConfiguration(),
@JsonProperty("xcodebuildTestArgs") val xcodebuildTestArgs: Map<String, String> = emptyMap(),
@JsonProperty("testParserConfiguration") val testParserConfiguration: com.malinskiy.marathon.config.vendor.ios.TestParserConfiguration = com.malinskiy.marathon.config.vendor.ios.TestParserConfiguration.NmTestParserConfiguration,
@JsonProperty("testParserConfiguration") val testParserConfiguration: com.malinskiy.marathon.config.vendor.ios.TestParserConfiguration = com.malinskiy.marathon.config.vendor.ios.TestParserConfiguration.NmTestParserConfiguration(),

@JsonProperty("signing") val signing: SigningConfiguration = SigningConfiguration(),
) : VendorConfiguration() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo
JsonSubTypes.Type(value = TestParserConfiguration.XCTestParserConfiguration::class, name = "xctest"),
)
sealed class TestParserConfiguration {
object NmTestParserConfiguration : TestParserConfiguration()
data class NmTestParserConfiguration(val testClassRegexes: Collection<Regex> = listOf(Regex("^((?!Abstract).)*Test[s]*$"))) : TestParserConfiguration() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as NmTestParserConfiguration

//For testing we need to compare configuration instances. Unfortunately Regex equality is broken so need to map it to String
return testClassRegexes.map { it.pattern } == other.testClassRegexes.map { it.pattern }
}

override fun hashCode(): Int {
return testClassRegexes.hashCode()
}
}
object XCTestParserConfiguration : TestParserConfiguration()
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ class ConfigurationFactoryTest {
TestFilterConfiguration.AnnotationFilterConfiguration(".*".toRegex()),
TestFilterConfiguration.AnnotationDataFilterConfiguration(".*".toRegex(), ".*".toRegex())
)
configuration.testClassRegexes.map { it.toString() } shouldContainSame listOf("^((?!Abstract).)*Test$")

// Regex doesn't have proper equals method. Need to check the patter itself
configuration.includeSerialRegexes.joinToString(separator = "") { it.pattern } shouldBeEqualTo """emulator-500[2,4]""".toRegex().pattern
Expand Down Expand Up @@ -189,7 +188,7 @@ class ConfigurationFactoryTest {
screenshotConfiguration = ScreenshotConfiguration(false, 1080, 1920, 200)
),
15000L,
AllureConfiguration()
AllureConfiguration(),
)
}

Expand Down Expand Up @@ -231,8 +230,6 @@ class ConfigurationFactoryTest {
configuration.filteringConfiguration.allowlist.shouldBeEmpty()
configuration.filteringConfiguration.blocklist.shouldBeEmpty()

configuration.testClassRegexes.map { it.toString() } shouldContainSame listOf("^((?!Abstract).)*Test[s]*$")

configuration.includeSerialRegexes shouldBeEqualTo emptyList()
configuration.excludeSerialRegexes shouldBeEqualTo emptyList()
configuration.ignoreFailures shouldBeEqualTo false
Expand Down
2 changes: 0 additions & 2 deletions configuration/src/test/resources/fixture/config/sample_1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ filteringConfiguration:
- type: "annotationData"
nameRegex: ".*"
valueRegex: ".*"
testClassRegexes:
- "^((?!Abstract).)*Test$"
includeSerialRegexes:
- "emulator-500[2,4]"
excludeSerialRegexes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ filteringConfiguration:
- type: "annotationData"
nameRegex: ".*"
valueRegex: ".*"
testClassRegexes:
- "^((?!Abstract).)*Test$"
includeSerialRegexes:
- "emulator-500[2,4]"
excludeSerialRegexes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ filteringConfiguration:
regex: ".*"
- type: "annotation"
regex: ".*"
testClassRegexes:
- "^((?!Abstract).)*Test$"
includeSerialRegexes:
- "emulator-500[2,4]"
excludeSerialRegexes:
Expand Down
4 changes: 1 addition & 3 deletions core/src/main/kotlin/com/malinskiy/marathon/Marathon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,7 @@ class Marathon(
}

private fun applyTestFilters(parsedTests: List<Test>): List<Test> {
var tests = parsedTests.filter { test ->
configuration.testClassRegexes.all { it.matches(test.clazz) }
}
var tests = parsedTests
configuration.filteringConfiguration.allowlist.forEach { tests = it.toTestFilter().filter(tests) }
configuration.filteringConfiguration.blocklist.forEach { tests = it.toTestFilter().filterNot(tests) }
return tests
Expand Down
1 change: 0 additions & 1 deletion docs/docs/android/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ marathon {
add(SimpleClassnameFilterConfiguration("$^".toRegex()))
}
}
testClassRegexes = listOf("^((?!Abstract).)*Test$")
includeSerialRegexes = emptyList()
excludeSerialRegexes = emptyList()
uncompletedTestRetryQuota = 100
Expand Down
1 change: 0 additions & 1 deletion docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ vendorConfiguration:
```yaml
name: "My application"
outputDir: "derived-data/Marathon"
testClassRegexes: ["^((?!Abstract).)*Tests$"]
vendorConfiguration:
type: "iOS"
bundle:
Expand Down
36 changes: 0 additions & 36 deletions docs/docs/intro/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,42 +113,6 @@ Refer to platform configuration for additional options inside the `vendorConfigu

## Optional

### Test class regular expression
By default, test classes are found using the ```"^((?!Abstract).)*Test[s]*$"``` regex. You can override this if you need to.

<Tabs>
<TabItem value="YAML" label="Marathonfile">

```yaml
testClassRegexes:
- "^((?!Abstract).)*Test[s]*$"
```

</TabItem>
<TabItem value="kts" label="Kotlin DSL">

```kotlin
marathon {
testClassRegexes = listOf(
"^((?!Abstract).)*Test[s]*$"
)
}
```

</TabItem>
<TabItem value="groovy" label="Groovy DSL">

```groovy
marathon {
testClassRegexes = [
"^((?!Abstract).)*Test[s]*\$"
]
}
```

</TabItem>
</Tabs>

### Ignore failures
By default, the build fails if some tests failed. If you want to the build to succeed even if some tests failed use *true*.

Expand Down
1 change: 0 additions & 1 deletion docs/docs/intro/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ vendorConfiguration:
```yaml
name: "My application"
outputDir: "derived-data/Marathon"
testClassRegexes: ["^((?!Abstract).)*Tests$"]
vendorConfiguration:
type: "iOS"
bundle:
Expand Down
14 changes: 13 additions & 1 deletion docs/docs/ios/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,19 @@ We don't provide source code for the libxctest-parser module. By using libxctest
Default test parser is nm.

<Tabs>
<TabItem value="YAML" label="Marathonfile">
<TabItem value="nm" label="nm">

```yaml
vendorConfiguration:
type: "iOS"
testParserConfiguration:
type: "nm"
testClassRegexes:
- "^((?!Abstract).)*Test[s]*$"
```

</TabItem>
<TabItem value="xctest" label="xctest">

```yaml
vendorConfiguration:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,6 @@ open class MarathonExtension {
*/
var uncompletedTestRetryQuota: Int? = null

/**
* By default, test classes are found using the ```"^((?!Abstract).)*Test[s]*$"``` regex. You can override this if you need to.
*/
var testClassRegexes: Collection<String>? = null


var includeSerialRegexes: Collection<String>? = null
var excludeSerialRegexes: Collection<String>? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ class MarathonPlugin : Plugin<Project> {
config.isCodeCoverageEnabled?.let { isCodeCoverageEnabled = it }
config.executionStrategy?.let { executionStrategy = it }
config.uncompletedTestRetryQuota?.let { uncompletedTestRetryQuota = it }
config.testClassRegexes?.map { it.toRegex() }?.let { testClassRegexes = it }
config.includeSerialRegexes?.map { it.toRegex() }?.let { includeSerialRegexes = it }
config.excludeSerialRegexes?.map { it.toRegex() }?.let { excludeSerialRegexes = it }
config.testBatchTimeoutMillis?.let { testBatchTimeoutMillis = it }
Expand Down
2 changes: 0 additions & 2 deletions sample/android-cucumber-app/Marathonfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: "android-cucumber-app tests"
outputDir: "build/reports/marathon"
isCodeCoverageEnabled: true
testClassRegexes:
- ".*"
retryStrategy:
type: "fixed-quota"
totalAllowedRetryQuota: 100
Expand Down
1 change: 0 additions & 1 deletion sample/ios-app/Marathonfile-uiTests
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
name: "sample-ios-app tests"
outputDir: "report/marathon-uiTests"
testClassRegexes: ["^((?!Abstract).)*Tests$"]
screenRecordingPolicy: ON_ANY
isCodeCoverageEnabled: true
flakinessStrategy:
Expand Down
3 changes: 2 additions & 1 deletion sample/ios-app/Marathonfile-unitTests
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
name: "sample-ios-app tests"
outputDir: "report/marathon-unitTests"
testClassRegexes: ["^((?!Abstract).)*Tests$"]
screenRecordingPolicy: ON_ANY
isCodeCoverageEnabled: true
flakinessStrategy:
Expand All @@ -27,6 +26,8 @@ vendorConfiguration:
username: malinskiy
key: ${HOME}/.ssh/marathon
knownHostsPath: ${HOME}/.ssh/known_hosts
testParserConfiguration:
type: nm
xcresult:
pull: true
remoteClean: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ import com.malinskiy.marathon.log.MarathonLogConfigurator
import org.koin.dsl.module

val AppleVendor = module {
single <DeviceProvider> {
val gson = GsonBuilder()
.registerTypeAdapter(SimctlDeviceList::class.java, SimctlDeviceListDeserializer())
.create()
val objectMapper = ObjectMapper(YAMLFactory().disable(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID))
.registerModule(
KotlinModule.Builder()
.withReflectionCacheSize(512)
.configure(KotlinFeature.NullToEmptyCollection, false)
.configure(KotlinFeature.NullToEmptyMap, false)
.configure(KotlinFeature.NullIsSameAsDefault, false)
.configure(KotlinFeature.SingletonSupport, true)
.configure(KotlinFeature.StrictNullChecks, false)
.build()
)
AppleDeviceProvider(get(), get(), get(), gson, objectMapper, get(), get())
single<DeviceProvider> {
val gson = GsonBuilder()
.registerTypeAdapter(SimctlDeviceList::class.java, SimctlDeviceListDeserializer())
.create()
val objectMapper = ObjectMapper(YAMLFactory().disable(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID))
.registerModule(
KotlinModule.Builder()
.withReflectionCacheSize(512)
.configure(KotlinFeature.NullToEmptyCollection, false)
.configure(KotlinFeature.NullToEmptyMap, false)
.configure(KotlinFeature.NullIsSameAsDefault, false)
.configure(KotlinFeature.SingletonSupport, true)
.configure(KotlinFeature.StrictNullChecks, false)
.build()
)
AppleDeviceProvider(get(), get(), get(), gson, objectMapper, get(), get())
}
single<TestParser?> {
val configuration = get<Configuration>()
Expand All @@ -46,7 +46,14 @@ val AppleVendor = module {
get()
)

else -> NmTestParser(get(), get(), get())
testParserConfiguration != null && testParserConfiguration is TestParserConfiguration.NmTestParserConfiguration -> NmTestParser(
get(),
get(),
testParserConfiguration,
get()
)

else -> NmTestParser(get(), get(), TestParserConfiguration.NmTestParserConfiguration(), get())
}
}
single<MarathonLogConfigurator> { AppleLogConfigurator(get()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.malinskiy.marathon.ios
import com.malinskiy.marathon.config.Configuration
import com.malinskiy.marathon.config.exceptions.ConfigurationException
import com.malinskiy.marathon.config.vendor.VendorConfiguration
import com.malinskiy.marathon.config.vendor.ios.TestParserConfiguration
import com.malinskiy.marathon.device.Device
import com.malinskiy.marathon.exceptions.TestParsingException
import com.malinskiy.marathon.execution.RemoteTestParser
Expand All @@ -16,6 +17,7 @@ import java.io.File
class NmTestParser(
private val configuration: Configuration,
private val vendorConfiguration: VendorConfiguration.IOSConfiguration,
private val parserConfiguration: TestParserConfiguration.NmTestParserConfiguration,
private val testBundleIdentifier: AppleTestBundleIdentifier
) : RemoteTestParser<AppleDeviceProvider> {
private val logger = MarathonLogging.logger(NmTestParser::class.java.simpleName)
Expand Down Expand Up @@ -89,7 +91,9 @@ class NmTestParser(
swiftTests.forEach { testBundleIdentifier.put(it, testBundle) }
objectiveCTests.forEach { testBundleIdentifier.put(it, testBundle) }

return swiftTests + objectiveCTests
return (swiftTests + objectiveCTests).filter { test ->
parserConfiguration.testClassRegexes.all { it.matches(test.clazz) }
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
name: "sample-ios-app tests"
outputDir: "derived-data/Marathon"
testClassRegexes: ["^((?!Abstract).)*Tests$"]
poolingStrategy:
- type: "omni"
batchingStrategy:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class ConfigurationFactory(val testParser: LocalTestParser, val deviceProvider:
var retryStrategy: RetryStrategyConfiguration = RetryStrategyConfiguration.NoRetryStrategyConfiguration
var shardingStrategy: ShardingStrategyConfiguration = ShardingStrategyConfiguration.ParallelShardingStrategyConfiguration
var sortingStrategy: SortingStrategyConfiguration = SortingStrategyConfiguration.NoSortingStrategyConfiguration
var testClassRegexes = listOf(Regex("^((?!Abstract).)*Test[s]*$"))
var testBatchTimeoutMillis = 180_000L
var testOutputTimeoutMillis = 60_000L
var analyticsTracking = false
Expand Down Expand Up @@ -69,7 +68,6 @@ class ConfigurationFactory(val testParser: LocalTestParser, val deviceProvider:
isCodeCoverageEnabled = this@ConfigurationFactory.isCodeCoverageEnabled
strictMode = this@ConfigurationFactory.strictMode
uncompletedTestRetryQuota = this@ConfigurationFactory.uncompletedTestRetryQuota
testClassRegexes = this@ConfigurationFactory.testClassRegexes
includeSerialRegexes = this@ConfigurationFactory.includeSerialRegexes
excludeSerialRegexes = this@ConfigurationFactory.excludeSerialRegexes
testBatchTimeoutMillis = this@ConfigurationFactory.testBatchTimeoutMillis
Expand Down

0 comments on commit a6c1281

Please sign in to comment.