From 631dd4537cf6c5062d23410f3721362c3e81006b Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Mon, 12 Oct 2026 18:25:26 +0600 Subject: [PATCH] [2026-10-12] eagle: personal/tech/legacy-xctest-runner.md --- personal/tech/legacy-xctest-runner.md | 76 +++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 personal/tech/legacy-xctest-runner.md diff --git a/personal/tech/legacy-xctest-runner.md b/personal/tech/legacy-xctest-runner.md new file mode 100644 index 00000000..9cff31f9 --- /dev/null +++ b/personal/tech/legacy-xctest-runner.md @@ -0,0 +1,76 @@ +--- +title: Legacy XCTest runner (run new-Xcode UI tests on macOS 12) +namespace: personal +updated: '2026-10-12' +tags: + - xctest + - ui-tests + - macos + - duckduckgo + - virfield +--- +# Legacy XCTest runner + +Runs DDG macOS UI tests built with the current Xcode (27.x) on a Mac that can only +run an old Xcode, e.g. the MBP 2014 node (Monterey 12.6.8, Intel, Xcode 13.4.1). + +Location: `~/Developer/legacy-xctest-runner/` (not committed anywhere). + +## Why it is needed + +- New Xcode's `XCTest.framework` and `UI Tests-Runner.app` require macOS 14+. +- The test bundle itself targets the app's deployment target (12.3), so it can run + if hosted by the old Xcode's runner. +- The bundle imports 2 Swift symbols missing from Xcode 13 XCTest: + `XCUIElement.typeKey(_:modifierFlags:)` (mangled under `XCUIAutomation`) and + `XCTIssue.init(…severity:)`. `XCTestCompat.swift` forwards them. + +## How it works + +- `package.sh ` — collects `DuckDuckGo Review.app`, + `tests-server`, `UI Tests.xctest` + runner files. +- `run.sh [--gui] [result-name]` on the target Mac: + - builds `XCTestCompat.framework` (re-exports old XCTest + libXCTestSwiftSupport, adds forwarders); + - hosts the bundle in Xcode 13's `XCTRunner.app`, `install_name_tool` repoints the + bundle's XCTest/libXCTestSwiftSupport imports at XCTestCompat; + - repeats `macOS UI Tests CI` scheme pre-actions (clean-app review, suppress + Move-to-Applications, start tests-server); + - `xcodebuild test-without-building` with `UITests.xctestrun` (FormatVersion 1), + then kills tests-server and the app (old XCTest doesn't terminate it). + - `--gui`: over SSH xcodebuild can't reach the runner; relaunches itself via a + Terminal `.command` in the console session, waits, closes finished windows. + +Build on the host (spell flags out — zsh doesn't word-split `$var`): + +```bash +xcodebuild build-for-testing -workspace DuckDuckGo.xcworkspace -scheme "macOS UI Tests CI" -destination "platform=macOS,arch=x86_64" -derivedDataPath
ONLY_ACTIVE_ARCH=YES -skipPackagePluginValidation -skipMacroValidation +xcodebuild build -workspace DuckDuckGo.xcworkspace -scheme "macOS Browser" -configuration Review -destination "platform=macOS,arch=x86_64" -derivedDataPath
ONLY_ACTIVE_ARCH=YES -skipPackagePluginValidation -skipMacroValidation +``` + +## Target Mac prerequisites (once per boot volume, needs sudo) + +```bash +sudo DevToolsSecurity -enable +sudo automationmodetool enable-automationmode-without-authentication +``` + +Without them testmanagerd shows an admin-password prompt on the display +("Timed out while enabling automation mode"). Virfield's node probe now reports +`ui_testing` (`ready` / `devtools_disabled` / `automation_mode_requires_auth` / +`no_console_session`); setup script `virfield-v3/deploy/node-ui-testing.sh`. + +## Gotchas found + +- Repo `Logger` (`macOS/UITests/Common/UITests.swift`) calls private + `-[XCTContext _recordActivityMessageWithFormat:]`; old XCTest lacks it → guard + with `responds(to:)` (done on branch `alex/fix-save-credentials-tooltip-crash-macos12`). +- Remote shell is zsh: `log` is a builtin — use `/usr/bin/log show`. +- MBP has a different SSH host key per boot volume; use the Virfield lease's + generated `ssh-config` (pins the booted volume's key). +- Hover tracking in the app uses `.activeInKeyWindow`; popovers that open without + focus don't get hover events. + +First used: 2026-10-12, reproducing Sentry crash +`NSInternalInconsistencyException SaveCredentialsViewController.loadView` +(`isfinite(newOrigin.x)` on macOS 12) — reproduced before fix on the MBP. +See also [[virfield]].