# UI Test Rules These rules are non-negotiable. Every test, every suite, every helper must follow them. ## Element Interaction 1. **All elements found by accessibility identifier** — never `label CONTAINS` for app elements 2. **No coordinate taps anywhere** — `app.coordinate(withNormalizedOffset:)` is banned 3. **Use screen objects for all interactions** — test bodies should read like user stories ## Timeouts 4. **`defaultTimeout` = 2 seconds** — if an element on the current screen isn't there in 2s, the app is broken 5. **`navigationTimeout` = 5 seconds** — screen transitions, tab switches 6. **No retry loops in test helpers** — tap once, check once, fail fast ## Independence 7. **Every suite runs alone, in combination, or in parallel** — no ordering dependencies 8. **Every test creates its own data via fixture seeding in setUp** 9. **No shared mutable state** — no `static var`, no class-level properties mutated across tests ## Clarity 10. **One logical assertion per test** — test name describes the exact behavior 11. **`XCTFail` with a message that tells you what went wrong** without reading the code 12. **No `guard ... else { return }` that silently passes** — if a precondition fails, `XCTFail` and stop ## Speed 13. **No `sleep()`, `usleep()`, or `Thread.sleep`** in tests — condition-based waits only 14. **Target: each individual test completes in under 15 seconds** (excluding setUp/tearDown) 15. **No swipe loops** — if content needs scrolling, use `scrollIntoView()` with a fail-fast bound ## Parallel Safety 16. **Each test process gets a unique session ID** — `UI_TEST_SESSION_ID` isolates UserDefaults and SwiftData 17. **In-memory SwiftData containers** — no shared on-disk state between parallel runners 18. **Session-scoped UserDefaults suites** — `uitest.` prevents cross-test contamination