iOS 端到端测试 是做什么的?
从检出根目录开始工作。本地 .mobilebuildmcp/config.yaml(设置)提供项目、方案和 DerivedData,因此 mobilebuildmcp 命令无需项目标志。
两个重复出现的值:
$sim:模拟器 UDID(pnpm ios:sim:pair会打印一个)。每次调用mobilebuildmcp时传递--simulator-id "$sim";否则配置默认使用名为iPhone 17的模拟器。$bundle:包 ID,取决于签名团队。从构建中读取:bundle=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' apps/ios/build/DerivedData/Build/Products/Debug-iphonesimulator/OpenClaw.app/Info.plist)。
构建并运行
-
构建:
mobilebuildmcp simulator build。编辑apps/ios/project.yml后,先运行pnpm ios:gen。 -
使用
simctl安装并启动,可传递启动参数(pnpm ios:run不接收参数):xcrun simctl install "$sim" apps/ios/build/DerivedData/Build/Products/Debug-iphonesimulator/OpenClaw.app xcrun simctl launch --terminate-running-process "$sim" "$bundle" --openclaw-reset-onboardingmobilebuildmcp simulator build-and-run和launch-app会附加一个永不退出的日志捕获。 -
调试启动参数:
grep -rhoE '"--openclaw-[a-z-]+"' apps/ios/Sources | sort -u。--openclaw-screenshot-mode加上--openclaw-*-fixture标志可在没有 Gateway 的情况下显示一个固定屏幕;-AppleLanguages "(de)" -AppleLocale de_DE以其他语言运行。调试 URL 方案为openclaw-debug://。
驱动 UI
mobilebuildmcp ui-automation snapshot-ui --style minimal以ref|action|role|label|value|id形式列出可点击目标。非控件的文本(聊天气泡、行标题)仅在--output json时出现。- 对 ref 执行
tap、type-text、long-press(--duration单位为毫秒)、swipe或gesture操作。使用wait-for-ui等待:--predicate exists --label '…' --role button等待元素,--predicate textContains --text '…'等待文本。匹配多个元素的等待选择器会失败;请添加--role或--identifier。将--timeout-ms保持在 30000 以下:守护进程会在 30 秒后以DAEMON_TRANSPORT_FAILED结束任何请求;如需更长时间则重复等待。 - Refs 属于单个快照;每次屏幕变化后请获取新的快照。
- 查看屏幕:
mobilebuildmcp simulator screenshot,然后读取打印的 JPEG。
注意事项:
- 引导流程和弹出菜单也会列出其背后的屏幕;按标签或 id 匹配并取最后一个匹配项。
- 在 iPhone 上,侧边栏会覆盖内容:在点击其行之前先点击
RootTabs.Sidebar.Show。 xcrun simctl openurl每次调用会排队一个系统“在 OpenClaw 中打开?”提示;每次需要点击打开或取消。- 应用进程外的系统 UI(照片选择器、分享表单)不在快照中。使用 MobileBuildMCP 附带的 AXe 二进制文件通过坐标点击:
"$(brew --prefix mobilebuildmcp)/libexec/bundled/axe" tap -x <x> -y <y> --udid "$sim"。坐标是点:截图像素 × 屏幕宽度(点)÷ 截图宽度。
日志和崩溃
先执行操作,然后读取有限的时间窗口:
xcrun simctl spawn "$sim" log show --last 2m --style compact --predicate 'subsystem BEGINSWITH "ai.openclaw"'
崩溃信息位于 ~/Library/Logs/DiagnosticReports/OpenClaw-*.ips;triggered 线程的第一个 OpenClaw 帧指明问题来源。应用偏好设置和数据库位于应用容器中(xcrun simctl get_app_container "$sim" "$bundle" data);simctl spawn … defaults read 无法访问它们。LLDB 和 xctrace:DEBUG.md。
测试
- 运行受影响测试套件:
pnpm ios:test <Suite>(选择器和IOS_SIM:见apps/ios/README.md)。 - 证明回归测试在基础分支上为红色:提交更改,检出更改源文件的基础版本(
git checkout <base> -- <paths>),运行测试套件,然后git checkout HEAD -- <paths>。
完成: 受影响的测试套件通过,每个新的回归测试在基础分支上失败。
证明变更的端到端正确性
- 以长期运行服务方式启动独立 Gateway(一次性配置文件,见设置):
node scripts/run-node.mjs --profile ios-sim gateway --bind loopback。它不会触及操作员的 Gateway 或~/.openclaw。运行时,通过node openclaw.mjs --profile ios-sim …调用 CLI;run-node在 Gateway 运行时拒绝重建。 - 通过真实的引导 UI 配对新模拟器:
sim=$(pnpm --silent ios:sim:pair | tail -1)(--app用于其他构建,--profile用于其他配置文件)。 - 通过可见控件操作变更。一个聊天往返:在
chat-message-input中输入内容,点击chat-send-message,然后等待回复中仅包含的单词。 - 比较构建:在
main和变更分支上分别执行相同步骤,每个分支使用独立的新模拟器,并截取匹配的截图。 - 停止 Gateway 并删除模拟器。
节点命令、权限、认证失败、服务中断、拒绝发送、升级和 iPad 布局:PROOF.md,其中也列出了只有真机才能证明的内容。
完成: 截图或录制的输出显示了变更分支上的行为及其在 main 上的缺失;Gateway 端口已关闭,且没有剩余的 openclaw-pair-* 模拟器。
设置
每台机器只需一次;每一步均以检查结束。
-
Xcode、模拟器运行时、
xcodegen和 Watch Rust 工具链:apps/ios/README.md中的先决条件。检查:xcrun simctl list devices available显示iPhone 17。 -
SwiftFormat 和 SwiftLint 使用仓库固定的版本:
scripts/install-swift-tools.sh <dir on PATH>。检查:scripts/check-swift-tools.sh退出码为 0。 -
MobileBuildMCP、Sentry 的 XcodeBuildMCP CLI:
brew tap getsentry/xcodebuildmcp && brew install getsentry/xcodebuildmcp/mobilebuildmcp。这些步骤基于版本 2.7.1。检查:mobilebuildmcp --version。 -
检出:
pnpm install --frozen-lockfile,然后pnpm ios:gen(Xcode 项目是生成的,不提交)。然后创建.mobilebuildmcp/config.yaml并将/.mobilebuildmcp/添加到.git/info/exclude:schemaVersion: 1 enabledWorkflows: [simulator, simulator-management, ui-automation, debugging] sentryDisabled: true sessionDefaults: projectPath: ./apps/ios/OpenClaw.xcodeproj scheme: OpenClaw configuration: Debug platform: iOS simulatorName: iPhone 17 derivedDataPath: ./apps/ios/build/DerivedData # 与 pnpm ios:run 共享检查:
mobilebuildmcp simulator list-schemes列出OpenClaw,并且mobilebuildmcp simulator build成功。 -
ios-simGateway 配置文件,Gateway 已停止(oc=node openclaw.mjs --profile ios-sim):oc config set gateway.mode local,oc config set gateway.port 19031,oc config set gateway.auth.mode token,oc config set gateway.auth.token "$(openssl rand -hex 24)"。聊天回复需要为其main智能体提供模型:oc models auth login或使用测试凭据add。检查:Gateway 启动,并且pnpm ios:sim:pair在聊天屏幕处结束。