12 KiB
Executable File
title, namespace, updated, tags
| title | namespace | updated | tags | |||||
|---|---|---|---|---|---|---|---|---|
| Legacy XCTest runner (run new-Xcode UI tests on macOS 12) | personal | 2026-10-17 |
|
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. macOS 12 + Xcode 13.4.1. Работает на двух типах целей:
- MBP 2014 node (Monterey 12.6.8, Intel x86_64), 2026-10-12;
- Tart VM из virfield, шаблон
monterey-xcode-13.4.1(macOS 12.7.6, arm64, Xcode 13.4.1 в/Applications/Xcode.app), 2026-10-17.
Location: ~/Developer/legacy-xctest-runner/ (not committed anywhere).
macOS 12 не входит в CI matrix (PR: только macOS 27; полный прогон: 14, 15, 27), это чисто локальная проверка. Минимум приложения — macOS 12.3.
Why it is needed
- New Xcode's
XCTest.frameworkandUI Tests-Runner.apprequire 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 underXCUIAutomation) andXCTIssue.init(…severity:).XCTestCompat.swiftforwards them (так чтоtypeKey(XCUIKeyboardKey, …)в тестах работает).
How it works
package.sh <derived-data> <out.tgz>— collectsDuckDuckGo Review.app,tests-server,UI Tests.xctest+ runner files. ЖдётBuild/Products/ReviewсDuckDuckGo Review.app,tests-server,UI Tests-Runner.app.run.sh [--gui] <TestClass[/testMethod]> [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_toolrepoints the bundle's XCTest/libXCTestSwiftSupport imports at XCTestCompat; - режет runner до нативного слайса (
lipo -thin, см. ниже), добавлено 2026-10-17; - repeats
macOS UI Tests CIscheme pre-actions (clean-app review, suppress Move-to-Applications, start tests-server); xcodebuild test-without-buildingwithUITests.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.commandin the console session, waits, closes finished windows.
- builds
- Env
SKIP_BUILD=1(патч на VM, в локальныйrun.shне внесён): пропуститьbuild_compatиassemble_runner, если уже собраны. Нужен для запуска по одному тесту.
Build on the host (spell flags out — zsh doesn't word-split $var):
xcodebuild build-for-testing -workspace DuckDuckGo.xcworkspace -scheme "macOS UI Tests CI" -destination "platform=macOS,arch=x86_64" -derivedDataPath <dd> ONLY_ACTIVE_ARCH=YES -skipPackagePluginValidation -skipMacroValidation
xcodebuild build -workspace DuckDuckGo.xcworkspace -scheme "macOS Browser" -configuration Review -destination "platform=macOS,arch=x86_64" -derivedDataPath <dd> ONLY_ACTIVE_ARCH=YES -skipPackagePluginValidation -skipMacroValidation
Для Apple Silicon VM архитектура arm64. Подписанное на хосте приложение 2026-10-17 собирали так: xcodebuild archive -scheme "macOS Browser Review" -configuration Review … EXCLUDED_ARCHS=x86_64 RELEASE_PRODUCT_NAME_OVERRIDE=DuckDuckGo + -exportArchive с копией macOS/scripts/assets/ExportOptions.plist (Developer ID, signingCertificate = SHA-1 из keychain; tracked plist не править, как делает archive.sh). Нотаризация внутри VM не нужна. Профили match Direct …review уже лежат в ~/Library/Developer/Xcode/UserData/Provisioning Profiles.
Target Mac prerequisites (once per boot volume, needs sudo)
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 /Users/admin/Developer/virfield/deploy/node-ui-testing.sh.
В Tart VM monterey-xcode-13.4.1 Developer Mode уже включён, sudo без пароля; automationmodetool выполнить надо.
Gotchas found
Запуск
- arm64e: SIGKILL 137 на старте раннера (Apple Silicon).
XCTRunner.appиз Xcode 13.4.1 — universalx86_64 arm64 arm64e, ядро выбирает arm64e:exec_mach_imgact: not running binary "UI Tests-Runner" built against preview arm64e ABI; xcodebuild: «Launched process exited during launch» /Failed to install or launch the test runner. Лечитсяlipo -thin $(uname -m)вassemble_runner(уже вrun.sh). На Intel не проявлялось. --guiзапускает себя из.commandпо$0; из SSH вызыватьrun.shтолько по абсолютному пути, иначе./run.sh: No such file or directoryв Terminal (cwd=home).LEGACY_XCODEиз окружения SSH не доходит до Terminal.command:xcrun: error: missing DEVELOPER_DIR path: /Applications/Xcode13.4.1.app. Либоsudo ln -sfn /Applications/Xcode.app /Applications/Xcode13.4.1.app, либо править дефолт.- Over SSH xcodebuild без
--guiне достаёт раннер; remote shell — zsh: нетtimeout(используйperl -e 'alarm N; exec @ARGV'),$varне делится на слова,log— builtin (/usr/bin/log show). - Exit code
.command-обёртки (exit=0в логах) не равен результату тестов. СмотретьExecuted N tests, with M failuresиTest Case … passed|failed.Executed 0 tests, with 1 failure= упал classsetUp. - Старый xcodebuild пишет
LLVM Profile Error: Failed to write file default.profraw: Read-only file system— безвредно. - Приложение: LSMinimumSystemVersion 12.3. arm64 VM требует arm64-сборку (Review app после
EXCLUDED_ARCHS=x86_64, test bundle arm64).
Тесты
- Старый XCTest не завершает приложение между тестами. При запуске класса целиком каждый следующий тест стартует поверх предыдущего:
Failed to synthesize event: Unable to synthesize gesture request N 'click' because gesture request M 'Type 'n' key with modifiers ⌘' is still in progress,Timed out while evaluating UI query, лавина падений без реальных assert (первый прогон: 49 «failures» на 25 тестах Duck.ai, 42 на 24 тестах поискового класса). Тот же тест по одному проходит за ~5 с. Решение: одинxcodebuildна каждый тест со свежимprepare_environment(чистые defaults, перезапуск tests-server и приложения),SKIP_BUILD=1после первого. 88 тестов ≈ 25–30 мин. Циклeach.shчитаетtests-list.txt(Class/method), пишетsummary-each.txt, запускается из Terminal.command. UITests.setAutocompleteToggleBeforeTestcaseRuns(false)на macOS 12 падает по таймауту (Failed to get matching snapshots: Timed out while evaluating UI query, окно Settings) → тесты класса не стартуют (Executed 0 tests, with 1 failure, ~190 с). Затронуты все классы с этимsetUp, включаяAddressBarKeyboardShortcutsTests. Локальный обход без коммита: убрать вызов хелпера при сборке бандла и вprepare_environmentписатьdefaults write com.duckduckgo.macos.browser.review preferences.appearance.show-autocomplete-suggestions -bool false.- Duck.ai: ввод сразу после Shift+Enter теряется, пока text view не получил фокус (на macOS 12 в ~3 из 25 тестов) → повторять Cmd+A и ввод, пока содержимое не совпало.
- Редкий флейк:
Failed to compute hit point for (null)→ раннер падает при снятии скриншота (Restarting after unexpected exit, crash, or test timeout, итогnoresult). Перезапуск одного теста помогает. - Repo
Logger(macOS/UITests/Common/UITests.swift) calls private-[XCTContext _recordActivityMessageWithFormat:]; old XCTest lacks it → guard withresponds(to:)(в main уже есть). - Hover tracking in the app uses
.activeInKeyWindow; popovers that open without focus don't get hover events. - Текст Duck.ai omnibar (
AIChatOmnibarTextContainerViewController.textView) не виден в accessibility-дереве (контейнер…view— одиночныйOther), в том числе на macOS 27. Ключи шлются черезapp.typeKey, текст читается через Cmd+A, Cmd+C иNSPasteboard.
Окружение / запись
screencapture -vна macOS 12 VM:capture error The operation could not be completedи по SSH, и из Terminal в GUI-сессии (нет Screen Recording TCC, SIP включён, выдать нельзя). На macOS 27 goldenuitest-27-v1работает по обычному SSH. Для macOS 12 записи экрана нет — только логи и.xcresult.- MBP has a different SSH host key per boot volume; use the Virfield lease's
generated
ssh-config(pins the booted volume's key). Для Tart VM IP (192.168.64.x) доступен напрямую с хоста. - Диск Tart:
samsung-tart≈214 ГБ, macOS 27 clone резервирует 140 ГБ, Monterey 120 ГБ — вместе не помещаются, см. virfield.
Находки на macOS 12 (PR 4548, address bar word selection)
2026-10-17, ветка alex/bug-08b-addressbar-selection: тесты Opt+Shift+←/→, Cmd+Shift+←/→, Shift+←/→, Cmd+A, delete/forward-delete в адресной строке (URL, поисковый запрос, суффикс) и Duck.ai.
- На macOS 12 после Cmd+Shift+←
selectionAffinityостаётся прежним (на 27 становится.upstream) → Opt+Shift+→ не сжимала выделение слева. Исправлено явной установкой affinity вAddressBarTextEditor(moveToBeginningOfLine/LeftEndOfLine/EndOfLine/RightEndOfLine…AndModifySelection). Тот же класс проблемы —selectAll: affinity теперь явно.downstream.
Результаты запусков
- 2026-10-12, MBP 2014 (Intel): воспроизведён Sentry crash
NSInternalInconsistencyException SaveCredentialsViewController.loadView(isfinite(newOrigin.x)on macOS 12) до фикса. - 2026-10-17, Tart VM macOS 12.7.6 arm64: по-тестовый прогон 88 новых тестов. Первый проход 85 passed / 2 failed (находка про Cmd+Shift+← affinity) / 1 noresult (флейк скриншота). После фикса три теста перепроверены — passed.
- Полный прогон на финальном коде: 85 passed / 3 failed. Все три — Duck.ai:
setUpнабирает prompt сразу после Shift+Enter, клавиши теряются, пока text view не взял фокус (XCTAssertEqual failed: ("") is not equal to ("alpha beta gamma delta")). В тесте добавлен retry (до 3 попыток Cmd+A и ввод), класс Duck.ai перегнан — 25/25 passed. Итого 88/88 на macOS 12. - Те же тесты на macOS 27 (Xcode 27.0) — 88/88 с записью экрана; PR 4548 в duckduckgo/apple-browsers, CI UI Tests на 14/15/27 запущен вручную (workflow_dispatch).
See also virfield.