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

2.2 KiB

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 anywhereapp.coordinate(withNormalizedOffset:) is banned

Timeouts

  1. defaultTimeout = 2 seconds — if an element on the current screen isn't there in 2s, the app is broken
  2. navigationTimeout = 5 seconds — screen transitions, tab switches
  3. loginTimeout = 15 seconds — initial auth flow only (cold start)
  4. No retry loops in test helpers — tap once, check once, fail fast

Independence

  1. Every suite runs alone, in combination, or in parallel — no ordering dependencies
  2. Every test gets its OWN isolated accountAuthenticatedUITestCase 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.
  3. No shared mutable state — no static var, no class-level properties mutated across tests

Clarity

  1. One logical assertion per test — test name describes the exact behavior
  2. XCTFail with a message that tells you what went wrong without reading the code
  3. No guard ... else { return } that silently passes — if a precondition fails, XCTFail and stop

Speed

  1. No sleep(), usleep(), or Thread.sleep in tests — condition-based waits only
  2. If focusAndType can't get focus in one tap, the test fails — no 3-attempt retry loops
  3. Target: each individual test completes in under 15 seconds (excluding setUp/tearDown)

Preconditions

  1. 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.