Add swift command for running UI tests

This commit is contained in:
Stefan Ceriu
2026-02-27 14:04:48 +02:00
committed by Stefan Ceriu
parent 3dfb33d6e9
commit 6e60aac0dc
4 changed files with 87 additions and 72 deletions

View File

@@ -8,6 +8,7 @@ struct CI: ParsableCommand {
subcommands: [
AccessibilityTests.self,
UnitTests.self,
UITests.self,
RunTests.self,
ConfigureNightly.self
])

View File

@@ -0,0 +1,79 @@
import ArgumentParser
import CommandLineTools
import Foundation
struct UITests: AsyncParsableCommand {
static let configuration = CommandConfiguration(commandName: "ui-tests",
abstract: "Runs the UI test CI workflow for a specific device type.",
discussion: """
Examples:
swift run tools ci ui-tests --device-type iPhone
swift run tools ci ui-tests --device-type iPad
swift run tools ci ui-tests --device-type iPhone --test-name "ClassName/testName"
""")
enum DeviceType: String, CaseIterable, ExpressibleByArgument {
case iPhone
case iPad
}
@Option(help: "The device type to test (iPhone or iPad).")
var deviceType: DeviceType
@Option(help: "iOS version for the simulator.")
var osVersion = "26.1"
@Option(help: "Run only a specific test (format: 'ClassName/testName').")
var testName: String?
private var simulatorName: String {
switch deviceType {
case .iPhone: "iPhone-\(osVersion)"
case .iPad: "iPad-\(osVersion)"
}
}
private var simulatorType: String {
switch deviceType {
case .iPhone: "com.apple.CoreSimulator.SimDeviceType.iPhone-17"
case .iPad: "com.apple.CoreSimulator.SimDeviceType.iPad-A16"
}
}
/// We used to run these simultaneously on iPhone and iPad but it is *really* slow on GitHub runners.
/// Presumably because launching 2 simulators uses more memory than the runner has available.
func run() async throws {
var args = [
"--scheme", "UITests",
"--device", simulatorName,
"--os-version", osVersion,
"--create-simulator-name", simulatorName,
"--create-simulator-type", simulatorType
]
if let testName {
args += ["--test-name", testName]
}
var testsFailed = false
do {
print("\n🧪 Running UI tests (\(deviceType.rawValue))…\n")
try await RunTests.parse(args).run()
} catch {
testsFailed = true
print("\n❌ UI tests (\(deviceType.rawValue)) failed.\n")
}
await CI.zipResults(bundles: ["UITests.xcresult"],
outputName: "UITests.xcresult.zip")
await CI.collectCoverage(resultBundle: "UITests.xcresult", outputName: "ui-cobertura.xml")
await CI.collectTestResults(resultBundle: "UITests.xcresult", outputName: "ui-junit.xml")
if testsFailed {
throw ExitCode.failure
}
print("\n✅ UI tests (\(deviceType.rawValue)) passed.\n")
}
}