名称:qa-testing-ios
描述:“使用xcodebuild和simctl在模拟器和设备上运行并稳定iOS测试(XCTest、XCUITest、Swift Testing):选择目标、管理模拟器状态、控制Flakes(区域设置/时间/网络/动画)、配置CI,并收集/解析xcresult工件。”
QA测试 (iOS)
使用xcodebuild和Xcode模拟器(simctl)来构建、运行和稳定iOS测试。
主要文档:XCTest、Swift Testing、simctl、Xcode测试
需要确认的输入
- Xcode入口点:
-workspace或-project
-scheme(以及可选的-testPlan)
- 目标:模拟器名称+iOS运行时(或
OS=latest),以及是否需要真实设备
- UI测试钩子:启动参数/环境切换(存根、演示数据、身份验证绕过、禁用动画)
- 工件需求:
xcresult、覆盖率、屏幕截图/视频、日志
快速命令
| 任务 |
命令 |
| 列出方案 |
xcodebuild -list -workspace MyApp.xcworkspace |
| 列出模拟器 |
xcrun simctl list devices |
| 列出设备(USB) |
xcrun xctrace list devices |
| 启动模拟器 |
xcrun simctl boot "iPhone 15 Pro" |
| 等待启动 |
xcrun simctl bootstatus booted -b |
| 构建应用 |
xcodebuild build -scheme MyApp -sdk iphonesimulator |
| 安装应用 |
xcrun simctl install booted app.app |
| 运行测试 |
xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15 Pro,OS=latest' -resultBundlePath TestResults.xcresult |
| 运行测试(设备) |
xcodebuild test -scheme MyApp -destination 'platform=iOS,id=<UDID>' -resultBundlePath TestResults.xcresult |
| 重置模拟器 |
xcrun simctl shutdown all && xcrun simctl erase all |
| 截取屏幕截图 |
xcrun simctl io booted screenshot screenshot.png |
| 录制视频 |
xcrun simctl io booted recordVideo recording.mov |
工作流程
- 解析构建输入(
workspace/project、scheme、testPlan、目标)。
- 使模拟器状态可重复:根据需要关闭/擦除、启动并等待启动。
- 启用工件运行测试(
-resultBundlePath);仅在适当时并行化和重试。
- 从
xcresult包中分类失败;通过重复确认Flakes;用所有者和重现步骤进行隔离。
xcodebuild模式
- 选择要重现的测试:
-only-testing:TargetTests/ClassName/testMethod和-skip-testing:TargetTests/FlakyClass。
- 对于大型测试套件优先使用测试计划:
-testPlan <plan>(保持设备/配置/运行一致)。
- 当测试套件隔离安全时启用并行测试:
-parallel-testing-enabled YES(+ -maximum-parallel-testing-workers N)。
- 在自动化中始终写入结果包:
-resultBundlePath TestResults.xcresult。
- 对于重运行,拆分构建和测试:
xcodebuild build-for-testing ...然后xcodebuild test-without-building ...。
- 本地检查结果:
open TestResults.xcresult或xcrun xcresulttool get --path TestResults.xcresult --format json。
Flake分类(重复和重试)
- 在添加重试之前,优先使用重复来证明Flake率。
- 在套件范围内重试之前,使用有针对性的重运行。
常见模式(标志因Xcode版本而异):
- 在CI中重试失败测试一次:
-retry-tests-on-failure -test-iterations 2
- 测量Flakiness直到首次失败:
-test-iterations 50 -test-repetition-mode until-failure
- 重复运行单个测试:
-only-testing:TargetTests/ClassName/testMethod -test-iterations 20
测试层次
| 层次 |
框架 |
范围 |
| 单元 |
XCTest / Swift Testing |
业务逻辑(快速) |
| 快照 |
XCTest + 快照库 |
视图渲染 |
| 集成 |
XCTest |
持久化、网络 |
| UI |
XCUITest |
关键用户旅程 |
设备矩阵
- 默认:PR门使用模拟器;发布使用真实设备
- 覆盖:一部小手机、一部大手机,如果支持则包括iPad
- 仅在支持多个主要版本时添加操作系统版本
Flake控制
除非项目另有要求,否则使用这些默认设置:
- 在UI测试构建中禁用或减少动画。
- 固定区域设置/时区(通过启动参数或应用级配置)。
- 在边界处存根网络(避免在UI测试中进行真实第三方调用)。
- 在测试之间重置应用状态(全新安装、深度链接重置或显式清理)。
- 优先使用基于状态的等待(
waitForExistence、期望)而不是睡眠。
- 在可能的情况下预授予/重置权限(模拟器):
xcrun simctl privacy booted grant ...。
CI集成(GitHub Actions)
name: iOS CI
on: [push, pull_request]
jobs:
test:
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: "16.0"
- run: |
set -euo pipefail
xcodebuild test \
-scheme MyApp \
-sdk iphonesimulator \
-destination 'platform=iOS Simulator,name=iPhone 15 Pro,OS=latest' \
-resultBundlePath TestResults.xcresult
- uses: actions/upload-artifact@v4
if: always()
with:
name: test-results
path: TestResults.xcresult
做 / 避免
做
- 使UI测试独立且幂等
- 使用测试数据构建器和专用测试账户
- 在失败时收集
xcresult包
- 使用accessibilityIdentifier,而非标签
避免
- 依赖测试顺序或全局状态
- 需要真实网络的UI测试
- 使用Thread.sleep()进行同步
- 未经验证就接受AI建议的选择器
资源
模板
相关技能