Add XCUITest authoring docs and reusable prompt template

This commit is contained in:
Trey t
2026-02-18 09:00:28 -06:00
parent 56ac783219
commit b58dfd5093
6 changed files with 262 additions and 29 deletions

View File

@@ -0,0 +1,85 @@
# XCUITest Authoring Guide
This document defines the required pattern for writing or modifying UI tests in this repository.
If a prompt says "create a UI test that does X", follow this guide exactly.
## Foundation Map
- Base class: `/Users/treyt/Desktop/code/Feels/Tests iOS/Helpers/BaseUITestCase.swift`
- Wait + ID helpers: `/Users/treyt/Desktop/code/Feels/Tests iOS/Helpers/WaitHelpers.swift`
- Screen objects: `/Users/treyt/Desktop/code/Feels/Tests iOS/Screens/`
- Accessibility IDs source: `/Users/treyt/Desktop/code/Feels/Shared/AccessibilityIdentifiers.swift`
- Test-mode launch and fixtures: `/Users/treyt/Desktop/code/Feels/Shared/UITestMode.swift`
## Non-Negotiable Rules
- Use `BaseUITestCase` for UI test suites.
- Use `UITestID` / accessibility identifiers as primary selectors.
- Use screen objects for navigation/actions/assertions.
- Use wait helpers (`waitForExistence`, `waitForDisappearance`, `tapWhenReady`).
- Do not use `sleep(...)`.
- Do not rely on localized labels as the only selector.
## Deterministic Setup
Pick the right fixture by overriding `seedFixture` in the test class:
- `"empty"`: no entries
- `"single_mood"`: one current-day mood
- `"week_of_moods"`: seven days of entries
Override launch behavior when needed:
- `skipOnboarding` (default `true`)
- `bypassSubscription` (default `true`)
- `expireTrial` (default `false`)
## Authoring Workflow
1. Define or confirm accessibility IDs in app code.
2. Mirror IDs in `UITestID` if needed.
3. Add/extend a screen object in `Tests iOS/Screens/`.
4. Create a suite in `Tests iOS/{Feature}Tests.swift` inheriting `BaseUITestCase`.
5. Keep tests focused on one behavior per test method.
6. Add screenshots at meaningful checkpoints for triage.
7. Run targeted suite first, then broader run if needed.
## Command Pattern
Targeted suite:
```bash
xcodebuild -project Feels.xcodeproj \
-scheme "Feels (iOS)" \
-destination 'platform=iOS Simulator,name=iPhone 16 Pro' \
-only-testing:"Tests iOS/<SuiteName>" \
test
```
Full iOS UI suite:
```bash
xcodebuild -project Feels.xcodeproj \
-scheme "Feels (iOS)" \
-destination 'platform=iOS Simulator,name=iPhone 16 Pro' \
-only-testing:"Tests iOS" \
test
```
## Definition Of Done For New UI Tests
- New test compiles and passes in targeted run.
- Selectors are identifier-first (not string-literal labels).
- No `sleep(...)` usage.
- Screen object methods are reused where applicable.
- Any new test-only IDs are added in app code + test helper enums.
## Prompt Contract (For Agents)
When asked to "create a UI test that does X", the implementation should include:
- Test suite + test method(s) in `Tests iOS/`
- Any required accessibility ID additions in app code
- Any required screen object additions
- Targeted test execution output summary

View File

@@ -0,0 +1,34 @@
//
// <Feature>Tests.swift
// Tests iOS
//
// Replace placeholders and move into Tests iOS/ when creating a real suite.
//
import XCTest
final class <Feature>Tests: BaseUITestCase {
// Choose fixture: "empty", "single_mood", "week_of_moods"
override var seedFixture: String? { "empty" }
// Override launch behavior only when needed for this feature.
// override var skipOnboarding: Bool { false }
// override var bypassSubscription: Bool { false }
// override var expireTrial: Bool { true }
func test<Behavior>() {
let tabBar = TabBarScreen(app: app)
// Navigate using screen objects.
let day = tabBar.tapDay()
// Interact using identifier-backed elements and helpers.
day.assertMoodHeaderVisible()
// Add an attachment for triage/debugging.
captureScreenshot(name: "<feature_behavior_state>")
// Assert outcome.
XCTAssertTrue(day.moodHeader.exists, "Expected day mood header to exist")
}
}