Files
honeyDueKMP/iosApp/HoneyDueUITests/TEST_RULES.md
T
Trey T 7cdd88b11a docs: TESTING.md + TEST_RULES.md for the isolation/domain model
Document the two-target layout, per-test Kratos account isolation, the
seed-before-login precondition rules (requiresResidence /
seedAccountPreconditions), how to run the phased runner, and how to add a suite.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 16:37:05 -05:00

33 lines
2.2 KiB
Markdown

# UI Test Rules
These rules are non-negotiable. Every test, every suite, every helper must follow them.
## Element Interaction
1. **All text fields use `fillTextField(identifier:)`** — never raw `tap()` + `typeText()` in test bodies
2. **All buttons/elements found by accessibility identifier** — never `label CONTAINS` for app elements
3. **No coordinate taps anywhere**`app.coordinate(withNormalizedOffset:)` is banned
## 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. **`loginTimeout` = 15 seconds** — initial auth flow only (cold start)
7. **No retry loops in test helpers** — tap once, check once, fail fast
## Independence
8. **Every suite runs alone, in combination, or in parallel** — no ordering dependencies
9. **Every test gets its OWN isolated account**`AuthenticatedUITestCase` mints a fresh Kratos identity per test (`uit_<domain>_<uuid>@test.honeydue.local`), seeds under its own token, and deletes it in tearDown (cascading all data). Never share an account across tests.
10. **No shared mutable state** — no `static var`, no class-level properties mutated across tests
## Clarity
11. **One logical assertion per test** — test name describes the exact behavior
12. **`XCTFail` with a message that tells you what went wrong** without reading the code
13. **No `guard ... else { return }` that silently passes** — if a precondition fails, `XCTFail` and stop
## Speed
14. **No `sleep()`, `usleep()`, or `Thread.sleep`** in tests — condition-based waits only
15. **If `focusAndType` can't get focus in one tap, the test fails** — no 3-attempt retry loops
16. **Target: each individual test completes in under 15 seconds** (excluding setUp/tearDown)
## Preconditions
17. **Seed UI-gated preconditions BEFORE login** — a fresh account is empty at login, so data the UI must display has to be seeded before the app loads it. Use `requiresResidence` (seeds a residence) or override `seedAccountPreconditions(_:)` to seed a full scenario via API. Preconditions are infrastructure, not what the test is testing — establish them via API, never UI.