Enable parallel UI test execution via per-session data isolation
Each test class now gets a unique session ID (UUID) passed to the app via UI_TEST_SESSION_ID environment variable. The app uses this to: - Route GroupUserDefaults to a session-specific UserDefaults suite, preventing tests from clobbering each other's AppStorage state - Create an in-memory SwiftData container instead of the shared on-disk App Group store, eliminating SQLite contention Refactored 8 test classes that bypassed BaseUITestCase.setUp() with custom launch args — they now use overridable `localeArguments` and `extraLaunchArguments` properties, keeping session ID injection centralized. Added `relaunchApp(resetState:bypassSubscription:)` to BaseUITestCase for tests that need mid-test relaunch with different subscription state. Includes a ParallelUITests.xctestplan with class-level parallelism enabled and random execution ordering. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,19 +1,18 @@
|
||||
import XCTest
|
||||
|
||||
class HierarchyDumpTest: XCTestCase {
|
||||
class HierarchyDumpTest: BaseUITestCase {
|
||||
override var seedFixture: String? { nil }
|
||||
|
||||
func testDumpAccessibilityTree() {
|
||||
let app = XCUIApplication()
|
||||
app.launchArguments = ["--ui-testing", "--reset-state", "--disable-animations", "--bypass-subscription", "--skip-onboarding"]
|
||||
app.launch()
|
||||
sleep(3)
|
||||
|
||||
print("\n=== ELEMENT QUERIES ===")
|
||||
print("otherElements[mood_header]: \(app.otherElements[\"mood_header\"].exists)")
|
||||
print("descendants[mood_header]: \(app.descendants(matching: .any)[\"mood_header\"].firstMatch.exists)")
|
||||
print("groups[mood_header]: \(app.groups[\"mood_header\"].exists)")
|
||||
print("scrollViews[mood_header]: \(app.scrollViews[\"mood_header\"].exists)")
|
||||
print("staticTexts[mood_header]: \(app.staticTexts[\"mood_header\"].exists)")
|
||||
print("buttons[mood_button_great]: \(app.buttons[\"mood_button_great\"].exists)")
|
||||
print("otherElements[mood_header]: \(app.otherElements["mood_header"].exists)")
|
||||
print("descendants[mood_header]: \(app.descendants(matching: .any)["mood_header"].firstMatch.exists)")
|
||||
print("groups[mood_header]: \(app.groups["mood_header"].exists)")
|
||||
print("scrollViews[mood_header]: \(app.scrollViews["mood_header"].exists)")
|
||||
print("staticTexts[mood_header]: \(app.staticTexts["mood_header"].exists)")
|
||||
print("buttons[mood_button_great]: \(app.buttons["mood_button_great"].exists)")
|
||||
print("tabBars count: \(app.tabBars.count)")
|
||||
if app.tabBars.count > 0 {
|
||||
let tb = app.tabBars.firstMatch
|
||||
@@ -21,15 +20,15 @@ class HierarchyDumpTest: XCTestCase {
|
||||
print(" tab button: \(b.identifier) label=\(b.label)")
|
||||
}
|
||||
}
|
||||
print("otherElements[settings_header]: \(app.otherElements[\"settings_header\"].exists)")
|
||||
|
||||
print("otherElements[settings_header]: \(app.otherElements["settings_header"].exists)")
|
||||
|
||||
print("\n=== HIERARCHY (first 200 lines) ===")
|
||||
let desc = app.debugDescription
|
||||
let lines = desc.components(separatedBy: "\n")
|
||||
for (i, line) in lines.prefix(200).enumerated() {
|
||||
print("\(i): \(line)")
|
||||
}
|
||||
|
||||
|
||||
XCTAssertTrue(true) // always pass
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user