Total rebrand across KMM project: - Kotlin package: com.example.casera -> com.tt.honeyDue (dirs + declarations) - Gradle: rootProject.name, namespace, applicationId - Android: manifest, strings.xml (all languages), widget resources - iOS: pbxproj bundle IDs, Info.plist, entitlements, xcconfig - iOS directories: Casera/ -> HoneyDue/, CaseraTests/ -> HoneyDueTests/, etc. - Swift source: all class/struct/enum renames - Deep links: casera:// -> honeydue://, .casera -> .honeydue - App icons replaced with honeyDue honeycomb icon - Domains: casera.treytartt.com -> honeyDue.treytartt.com - Bundle IDs: com.tt.casera -> com.tt.honeyDue - Database table names preserved Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
84 lines
4.2 KiB
Markdown
84 lines
4.2 KiB
Markdown
# honeyDue iOS UI Testing Architecture
|
|
|
|
## Directory Structure
|
|
|
|
```
|
|
HoneyDueUITests/
|
|
├── PageObjects/ # Screen abstractions (Page Object pattern)
|
|
│ ├── BaseScreen.swift # Common wait/assert utilities
|
|
│ ├── LoginScreen.swift # Login screen elements and actions
|
|
│ ├── RegisterScreen.swift # Registration screen
|
|
│ └── MainTabScreen.swift # Main tab navigation + settings + logout
|
|
├── TestConfiguration/ # Launch config, environment setup
|
|
│ └── TestLaunchConfig.swift
|
|
├── Fixtures/ # Test data builders
|
|
│ └── TestFixtures.swift
|
|
├── CriticalPath/ # Must-pass tests for CI gating
|
|
│ ├── SmokeTests.swift # Fast smoke suite (<2 min)
|
|
│ ├── AuthCriticalPathTests.swift # Auth flow validation
|
|
│ └── NavigationCriticalPathTests.swift # Tab + navigation validation
|
|
├── UITestHelpers.swift # Shared login/logout/navigation helpers
|
|
├── AccessibilityIdentifiers.swift # UI element IDs (synced with app-side copy)
|
|
└── README.md # This file
|
|
```
|
|
|
|
## Test Suites
|
|
|
|
| Suite | Purpose | CI Gate | Target Time |
|
|
|-------|---------|---------|-------------|
|
|
| SmokeTests | App launches, basic auth, tab existence | Every PR | <2 min |
|
|
| AuthCriticalPathTests | Login, logout, registration entry, forgot password | Every PR | <3 min |
|
|
| NavigationCriticalPathTests | Tab navigation, settings, add buttons | Every PR | <3 min |
|
|
|
|
## Patterns
|
|
|
|
### Page Object Pattern
|
|
Every screen has a corresponding PageObject in `PageObjects/`. Use these instead of raw XCUIElement queries in tests. Page objects encapsulate element lookups and common actions, making tests more readable and easier to maintain when the UI changes.
|
|
|
|
### Wait Helpers
|
|
NEVER use `sleep()` or `Thread.sleep()`. Use `waitForElement()`, `waitForElementToDisappear()`, `waitForHittable()`, or `waitForCondition()` from BaseScreen. These are condition-based waits that return as soon as the condition is met, making tests both faster and more reliable.
|
|
|
|
### Test Data
|
|
Use `TestFixtures` builders for consistent, unique test data. Random numbers and UUIDs ensure test isolation so tests can run in any order without interfering with each other.
|
|
|
|
### Launch Configuration
|
|
Use `TestLaunchConfig.launchApp()` for standard launches. Use `launchAuthenticated()` to skip login when the app supports test authentication bypass. The standard configuration disables animations and forces English locale.
|
|
|
|
### Accessibility Identifiers
|
|
All interactive elements must have identifiers defined in `AccessibilityIdentifiers.swift`. Use `.accessibilityIdentifier()` in SwiftUI views. Page objects reference these identifiers for element lookup. The test-side copy must stay in sync with the app-side copy at `iosApp/Helpers/AccessibilityIdentifiers.swift`.
|
|
|
|
## CI Configuration
|
|
|
|
### Critical Path (every PR)
|
|
```bash
|
|
xcodebuild test -project iosApp.xcodeproj -scheme iosApp \
|
|
-sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 17' \
|
|
-only-testing:HoneyDueUITests/SmokeTests \
|
|
-only-testing:HoneyDueUITests/AuthCriticalPathTests \
|
|
-only-testing:HoneyDueUITests/NavigationCriticalPathTests
|
|
```
|
|
|
|
### Full Regression (nightly)
|
|
```bash
|
|
xcodebuild test -project iosApp.xcodeproj -scheme iosApp \
|
|
-sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 17' \
|
|
-only-testing:HoneyDueUITests
|
|
```
|
|
|
|
## Flake Reduction
|
|
|
|
- Target: <2% flake rate on critical-path suite
|
|
- All waits use condition-based predicates (zero fixed sleeps)
|
|
- Test data uses unique identifiers to prevent cross-test interference
|
|
- UI animations disabled via launch arguments
|
|
- Element lookups use accessibility identifiers exclusively
|
|
|
|
## Adding New Tests
|
|
|
|
1. If the screen does not have a page object yet, create one in `PageObjects/` that extends `BaseScreen`.
|
|
2. Define accessibility identifiers in `AccessibilityIdentifiers.swift` for any new UI elements.
|
|
3. Sync the app-side copy of `AccessibilityIdentifiers.swift` with matching identifiers.
|
|
4. Add test data builders to `TestFixtures.swift` if needed.
|
|
5. Write the test in `CriticalPath/` for must-pass CI tests.
|
|
6. Verify zero `sleep()` calls before merging.
|