c52ce4d497
Migrate the XCUITest suite off the legacy shared-account model (and the prior Django-style auth assumptions) to a parallel-safe, domain-organized architecture, validated end-to-end against the live Kratos stack. Isolation (parallel-safe by construction): - Core/Fixtures/TestAccount.swift: each test mints its own pre-verified Kratos identity (uit_<domain>_<uuid>@test.honeydue.local), logs in, seeds under its own token, and deletes the identity in teardown (cascading all data + clearing Kratos). No shared testuser; parallel workers no longer race. - AuthenticatedUITestCase rewritten to that model (member surface preserved); adds requiresResidence / seedAccountPreconditions to seed UI-gated data BEFORE login (a fresh account is empty at login). Organization (255 tests preserved, none dropped): - 21 domain suites under Auth/ Onboarding/ Residence/ Task/ Contractor/ Document/ Sharing/ Navigation/ Smoke/ CrossCutting/ E2E/, consistent <Domain>UITests naming. Removes the Suite1..11 / AAA_ / ZZ_ / Tests/Rebuild naming chaos and the overlapping task/residence/auth suites. Runner + test plans: - run_ui_tests.sh: Smoke gate -> Seed -> Parallel(8 workers) -> Sweep. The parallel phase runs the whole target minus phase-managed suites via -skip-testing, so new suites auto-include (no hand-maintained list to drift). Drops the 2-worker cap and Suite6 isolation (isolation made them moot). - HoneyDueUITests.xctestplan skips the 4 phase-managed suites; adds Smoke.xctestplan. Kratos auth fixes folded in (login/verify/reset endpoints removed under Kratos): real Mailpit verification codes replace the obsolete fixed "123456"; teardown deletes Kratos identities; admin-panel login uses the correct seeded password. Build green; isolation, parallelism, and the precondition/sharing migrations validated against the live stack (0 leaked accounts). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
140 lines
5.9 KiB
Bash
Executable File
140 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
|
# run_ui_tests.sh — Phased UI test runner.
|
|
#
|
|
# Architecture: every test mints its OWN isolated Kratos account (see
|
|
# Core/Fixtures/TestAccount.swift + AuthenticatedUITestCase), so suites are
|
|
# fully independent and the parallel phase scales to many workers with no
|
|
# cross-suite data races. There is no per-suite ordering and no Suite6
|
|
# special-casing anymore.
|
|
#
|
|
# Phases:
|
|
# 0. Smoke gate — fast launch/login sanity. Abort the run if it fails.
|
|
# 1. Seed — ensure baseline accounts exist (AAA_SeedTests).
|
|
# 2. Parallel — the WHOLE target minus the four phase-managed suites, via
|
|
# -skip-testing. New suites are auto-included (no hand-
|
|
# maintained list to drift), run at $WORKERS workers.
|
|
# 3. Sweep — clear-all-data + delete leaked uit_* Kratos identities
|
|
# (SuiteZZ_CleanupTests). Non-blocking.
|
|
#
|
|
# Usage:
|
|
# ./run_ui_tests.sh # iPhone 17 Pro, 8 workers
|
|
# ./run_ui_tests.sh "iPhone Air" 6 # custom device + worker count
|
|
# ./run_ui_tests.sh --skip-seed # skip phase 1
|
|
# ./run_ui_tests.sh --skip-cleanup # skip phase 3
|
|
# ./run_ui_tests.sh --only-parallel # only phase 2
|
|
# ./run_ui_tests.sh --smoke # only phase 0
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
PROJECT="$SCRIPT_DIR/honeyDue.xcodeproj"
|
|
SCHEME="HoneyDueUITests"
|
|
TARGET="HoneyDueUITests"
|
|
DESTINATION="platform=iOS Simulator,name=iPhone 17 Pro"
|
|
WORKERS=8
|
|
|
|
# Suites that run in their own phases — excluded from the parallel phase.
|
|
PHASE_MANAGED=(
|
|
"$TARGET/AAA_SeedTests"
|
|
"$TARGET/SuiteZZ_CleanupTests"
|
|
"$TARGET/SmokeUITests"
|
|
"$TARGET/AppLaunchUITests"
|
|
)
|
|
|
|
SKIP_SEED=false
|
|
SKIP_CLEANUP=false
|
|
ONLY_PARALLEL=false
|
|
ONLY_SMOKE=false
|
|
|
|
POSITIONAL_ARGS=()
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--skip-seed) SKIP_SEED=true ;;
|
|
--skip-cleanup) SKIP_CLEANUP=true ;;
|
|
--only-parallel) ONLY_PARALLEL=true; SKIP_SEED=true; SKIP_CLEANUP=true ;;
|
|
--smoke) ONLY_SMOKE=true ;;
|
|
*) POSITIONAL_ARGS+=("$arg") ;;
|
|
esac
|
|
done
|
|
[ ${#POSITIONAL_ARGS[@]} -ge 1 ] && DESTINATION="platform=iOS Simulator,name=${POSITIONAL_ARGS[0]}"
|
|
[ ${#POSITIONAL_ARGS[@]} -ge 2 ] && WORKERS="${POSITIONAL_ARGS[1]}"
|
|
|
|
RESULTS_DIR="$SCRIPT_DIR/build/test-results"
|
|
DERIVED_DATA="$SCRIPT_DIR/build/DerivedData"
|
|
mkdir -p "$RESULTS_DIR" "$DERIVED_DATA"
|
|
|
|
BOLD='\033[1m'; GREEN='\033[0;32m'; RED='\033[0;31m'; YELLOW='\033[0;33m'; RESET='\033[0m'
|
|
phase_header() { echo ""; echo -e "${BOLD}════════════════════════════════════════════════════${RESET}"; echo -e "${BOLD} $1${RESET}"; echo -e "${BOLD}════════════════════════════════════════════════════${RESET}"; echo ""; }
|
|
|
|
run_xcodebuild() {
|
|
local result_path="$RESULTS_DIR/$1.xcresult"; shift
|
|
rm -rf "$result_path"
|
|
xcodebuild test \
|
|
-project "$PROJECT" -scheme "$SCHEME" -destination "$DESTINATION" \
|
|
-derivedDataPath "$DERIVED_DATA" -resultBundlePath "$result_path" \
|
|
"$@" 2>&1 | tail -40
|
|
return ${PIPESTATUS[0]}
|
|
}
|
|
|
|
OVERALL_START=$(date +%s)
|
|
|
|
# ── Phase 0: Smoke gate ────────────────────────────────────────
|
|
if [ "$ONLY_PARALLEL" = false ]; then
|
|
phase_header "Phase 0: Smoke gate"
|
|
if run_xcodebuild "Smoke" \
|
|
-only-testing:"$TARGET/SmokeUITests" \
|
|
-only-testing:"$TARGET/AppLaunchUITests"; then
|
|
echo -e "${GREEN}✓ Smoke passed${RESET}"
|
|
else
|
|
echo -e "${RED}✗ Smoke FAILED — aborting (app can't launch/log in).${RESET}"
|
|
exit 1
|
|
fi
|
|
[ "$ONLY_SMOKE" = true ] && exit 0
|
|
fi
|
|
|
|
# ── Phase 1: Seed ──────────────────────────────────────────────
|
|
if [ "$SKIP_SEED" = false ]; then
|
|
phase_header "Phase 1: Seed baseline accounts"
|
|
if run_xcodebuild "Seed" -only-testing:"$TARGET/AAA_SeedTests"; then
|
|
echo -e "${GREEN}✓ Seed passed${RESET}"
|
|
else
|
|
echo -e "${RED}✗ Seed FAILED — aborting.${RESET}"; exit 1
|
|
fi
|
|
fi
|
|
|
|
# ── Phase 2: Parallel (whole target minus phase-managed) ───────
|
|
phase_header "Phase 2: Parallel suite ($WORKERS workers)"
|
|
SKIP_ARGS=()
|
|
for t in "${PHASE_MANAGED[@]}"; do SKIP_ARGS+=( -skip-testing:"$t" ); done
|
|
PARALLEL_START=$(date +%s)
|
|
if run_xcodebuild "Parallel" \
|
|
-only-testing:"$TARGET" "${SKIP_ARGS[@]}" \
|
|
-parallel-testing-enabled YES -parallel-testing-worker-count "$WORKERS"; then
|
|
PARALLEL_PASSED=true; echo -e "${GREEN}✓ Parallel phase passed${RESET}"
|
|
else
|
|
PARALLEL_PASSED=false; echo -e "${RED}✗ Parallel phase FAILED${RESET}"
|
|
fi
|
|
PARALLEL_END=$(date +%s)
|
|
|
|
# ── Phase 3: Sweep ─────────────────────────────────────────────
|
|
if [ "$SKIP_CLEANUP" = false ]; then
|
|
phase_header "Phase 3: Sweep leaked accounts + data"
|
|
if run_xcodebuild "Sweep" -only-testing:"$TARGET/SuiteZZ_CleanupTests"; then
|
|
echo -e "${GREEN}✓ Sweep passed${RESET}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Sweep failed (non-blocking)${RESET}"
|
|
fi
|
|
fi
|
|
|
|
# ── Summary ────────────────────────────────────────────────────
|
|
phase_header "Summary"
|
|
echo " Total time: $(( $(date +%s) - OVERALL_START ))s"
|
|
echo " Parallel: $(( PARALLEL_END - PARALLEL_START ))s @ $WORKERS workers"
|
|
echo " Results: $RESULTS_DIR/"
|
|
echo ""
|
|
if [ "${PARALLEL_PASSED:-false}" = true ]; then
|
|
echo -e " ${GREEN}${BOLD}ALL TESTS PASSED${RESET}"; exit 0
|
|
else
|
|
echo -e " ${RED}${BOLD}TESTS FAILED${RESET} — open $RESULTS_DIR/"; exit 1
|
|
fi
|