Skip to content

Commit

Permalink
fix(ios): support flutter via patrol's only-testing option
Browse files Browse the repository at this point in the history
requires augmenting test parser and xcodebuild's result parser
  • Loading branch information
Malinskiy committed Jan 9, 2024
1 parent 0106217 commit 6c2a62d
Show file tree
Hide file tree
Showing 9 changed files with 30 additions and 38 deletions.
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.vendor.VendorConfiguration
import com.malinskiy.marathon.ios.executor.listener.AppleTestRunListener
import com.malinskiy.marathon.ios.extensions.testBundle
import com.malinskiy.marathon.ios.test.TestEvent
import com.malinskiy.marathon.ios.test.TestPassed
import com.malinskiy.marathon.ios.test.TestFailed
Expand Down Expand Up @@ -40,6 +41,7 @@ class AppleDeviceTestRunner(private val device: AppleSimulatorDevice, private va
tests = rawTestBatch.tests,
xcresult = remoteXcresultPath,
coverage = configuration.isCodeCoverageEnabled,
testTargetName = vendorConfiguration.testBundle().testBundleId,
)
var channel: ReceiveChannel<List<TestEvent>>? = null
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import com.malinskiy.marathon.ios.executor.listener.TestResultsListener
import com.malinskiy.marathon.ios.executor.listener.TestRunListenerAdapter
import com.malinskiy.marathon.ios.executor.listener.screenshot.ScreenCapturerTestRunListener
import com.malinskiy.marathon.ios.logparser.XctestEventProducer
import com.malinskiy.marathon.ios.logparser.formatter.NoopPackageNameFormatter
import com.malinskiy.marathon.ios.logparser.parser.DebugLogPrinter
import com.malinskiy.marathon.ios.logparser.parser.DeviceFailureException
import com.malinskiy.marathon.ios.logparser.parser.DiagnosticLogsPathFinder
Expand Down Expand Up @@ -349,7 +348,7 @@ class AppleSimulatorDevice(
withContext(Dispatchers.IO) {
val deferredStdout = supervisorScope {
async {
val testEventProducer = XctestEventProducer(NoopPackageNameFormatter, timer)
val testEventProducer = XctestEventProducer(request.testTargetName ?: "", timer)
for (line in session.stdout) {
testEventProducer.process(line)?.let {
send(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.malinskiy.marathon.device.Device
import com.malinskiy.marathon.exceptions.TestParsingException
import com.malinskiy.marathon.execution.RemoteTestParser
import com.malinskiy.marathon.execution.withRetry
import com.malinskiy.marathon.ios.extensions.testBundle
import com.malinskiy.marathon.ios.model.AppleTestBundle
import com.malinskiy.marathon.ios.test.TestEvent
import com.malinskiy.marathon.ios.test.TestRequest
Expand Down Expand Up @@ -77,7 +78,9 @@ class XCTestParser(
for (event in events) {
when (event) {
is TestStarted -> {
tests.add(event.id)
//Target name is never printed via xcodebuild. We create it using the bundle id in com.malinskiy.marathon.ios.xctestrun.TestRootFactory
val testWithTargetName = event.id.copy(pkg = vendorConfiguration.testBundle().testBundleId)
tests.add(testWithTargetName)
}
else -> Unit
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
package com.malinskiy.marathon.ios.logparser

import com.malinskiy.marathon.ios.logparser.formatter.PackageNameFormatter
import com.malinskiy.marathon.ios.logparser.parser.DeviceFailureParser
import com.malinskiy.marathon.ios.logparser.parser.TestRunProgressParser
import com.malinskiy.marathon.ios.test.TestEvent
import com.malinskiy.marathon.time.Timer

/**
* Currently doesn't provide any guarantee on the methods that should be called even once
*
* @param targetName target name (or blueprint name) is not printed by xcodebuild output, we have to augment the results to still have
* 'target/class_name/test_name' structure mapped properly to marathon's package.class.method
*/
class XctestEventProducer(packageNameFormatter: PackageNameFormatter, timer: Timer) : TestEventProducer {
class XctestEventProducer(targetName: String, timer: Timer) : TestEventProducer {
private val failureParser = DeviceFailureParser()
private val testRunListener = TestRunProgressParser(timer, packageNameFormatter)
private val testRunListener = TestRunProgressParser(timer, targetName)

override fun process(line: String): List<TestEvent>? {
return failureParser.process(line) ?: testRunListener.process(line)
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.malinskiy.marathon.ios.logparser.parser

import com.malinskiy.marathon.ios.logparser.TestEventProducer
import com.malinskiy.marathon.ios.logparser.formatter.PackageNameFormatter
import com.malinskiy.marathon.ios.test.TestEvent
import com.malinskiy.marathon.ios.test.TestFailed
import com.malinskiy.marathon.ios.test.TestIgnored
Expand All @@ -14,14 +13,14 @@ import kotlin.math.roundToInt

class TestRunProgressParser(
private val timer: Timer,
private val packageNameFormatter: PackageNameFormatter,
private val targetName: String,
) : TestEventProducer {

val logger = MarathonLogging.logger(TestRunProgressParser::class.java.simpleName)

val TEST_CASE_STARTED = """Test Case '-\[([a-zA-Z0-9_.]+) ([a-zA-Z0-9_]+)]' started\.""".toRegex()
val TEST_CASE_STARTED = """Test Case '-\[([a-zA-Z0-9_.]+) ([a-zA-Z0-9_ ]+)]' started\.""".toRegex()
val TEST_CASE_FINISHED =
"""Test Case '-\[([a-zA-Z0-9_.]+) ([a-zA-Z0-9_]+)]' (passed|failed|skipped) \(([\d\.]+) seconds\)\.""".toRegex()
"""Test Case '-\[([a-zA-Z0-9_.]+) ([a-zA-Z0-9_ ]+)]' (passed|failed|skipped) \(([\d\.]+) seconds\)\.""".toRegex()

/**
* $1 = file
Expand Down Expand Up @@ -65,8 +64,13 @@ class TestRunProgressParser(
var pkg: String? = null
var clazz: String? = null
if (pkgWithClass != null) {
pkg = packageNameFormatter.format(pkgWithClass.substringBeforeLast('.', missingDelimiterValue = ""))
clazz = pkgWithClass.substringAfter('.', missingDelimiterValue = pkgWithClass)
if (pkgWithClass.contains('.')) {
pkg = pkgWithClass.substringBeforeLast('.', missingDelimiterValue = "")
clazz = pkgWithClass.substringAfter('.', missingDelimiterValue = pkgWithClass)
} else {
pkg = targetName
clazz = pkgWithClass
}
}

val method = matchResult?.groups?.get(2)?.value
Expand Down Expand Up @@ -111,8 +115,13 @@ class TestRunProgressParser(
var pkg: String? = null
var clazz: String? = null
if (pkgWithClass != null) {
pkg = packageNameFormatter.format(pkgWithClass.substringBeforeLast('.', missingDelimiterValue = ""))
clazz = pkgWithClass.substringAfter('.', missingDelimiterValue = pkgWithClass)
if (pkgWithClass.contains('.')) {
pkg = pkgWithClass.substringBeforeLast('.', missingDelimiterValue = "")
clazz = pkgWithClass.substringAfter('.', missingDelimiterValue = pkgWithClass)
} else {
pkg = targetName
clazz = pkgWithClass
}
}
val method = matchResult?.groups?.get(2)?.value

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ data class TestRequest(
val coverage: Boolean,
val tests: List<Test>? = null,
val xcresult: String? = null,
val testTargetName: String? = null,
) {
fun toXcodebuildTestFilter(): Array<String> {
return tests?.map { "'-only-testing:${it.toTestName(packageSeparator = '/', methodSeparator = '/')}'" }?.toTypedArray() ?: emptyArray()
Expand Down

0 comments on commit 6c2a62d

Please sign in to comment.