XCUITest 是 Apple 用于 iOS、iPadOS 和 macOS 应用 UI 测试的框架,直接内置于 XCTest 和 Xcode 中。它允许模拟用户操作:点击、文本输入、滑动、滚动和手势——并可访问界面元素的内部状态。根据 Apple Developer Documentation, 2025,XCUIApplication 是所有 UI 测试的入口点,并提供对屏幕元素层次的访问。
要点
XCUITest 是 Apple 在 Xcode 7(2015 年)中发布的 UI 测试框架。它取代了 UI Automation (UIA),并成为 Apple 平台上自动化界面测试的标准工具。XCUITest 完全集成到 XCTest——Apple 的统一测试框架中。
与在类和方法级别检查逻辑的单元测试不同,XCUITest 通过模拟操作测试用户界面。测试在与应用程序分离的进程中运行,并通过 Accessibility API 与其交互——这确保了隔离性和可靠性。
XCUITest 不需要安装第三方服务器(与 Appium 不同)或额外的库来与设备交互。所需的一切都已包含在 Xcode 中。这确保了与新 iOS 版本的最佳兼容性,并立即访问新的手势和控件。
XCUITest 的架构基于两个关键类:XCUIApplication — 正在运行的测试应用程序,以及 XCUIElement — 界面元素。XCTest 测试运行器管理测试的生命周期:setUp、测试方法、tearDown。XCUITest 作为独立进程运行,通过 Accessibility 桥控制应用程序。
每个 UI 元素由 XCUIElement 对象表示,该对象包含用于查询状态(exists、isHittable、label、value)和操作(tap、pressForDuration、swipeUp、typeText)的方法。元素通过查询链组织成层次结构:app.buttons[].staticTexts[].tables[]。这允许灵活地找到屏幕上的任何元素。
XCUITest 使用 Accessibility 属性来识别元素:accessibilityIdentifier — 编程标识符,以及 accessibilityLabel — 供 VoiceOver 使用的描述。建议在应用程序代码中设置 accessibilityIdentifier——这使测试独立于本地化和布局而保持稳定。
XCUITest 测试使用 Swift 语言和 XCTest 语法编写。每个测试类继承自 XCTestCase,并包含以 test 开头的方法。在 setUp 方法中,应用程序以所需配置启动,在 tearDown 中进行清理和会话结束。
典型测试:查找元素 → 执行操作 → 检查结果。元素搜索通过 XCUIElementQuery 子查询进行:app.buttons["loginButton"]、app.textFields["email"]。操作:.tap()、.typeText("text")、.swipeUp()。检查:XCTAssertTrue(element.exists) 或 XCTAssertEqual(element.label, "expected")。
import XCTest
class LoginTests: XCTestCase {
let app = XCUIApplication()
override func setUp() {
continueAfterFailure = false
app.launch()
}
func testLoginWithValidCredentials() {
let emailField = app.textFields["emailInput"]
emailField.tap()
emailField.typeText("user@test.com")
let passwordField = app.secureTextFields["passwordInput"]
passwordField.tap()
passwordField.typeText("password123")
app.buttons["loginButton"].tap()
let homeLabel = app.staticTexts["homeTitle"]
XCTAssertTrue(homeLabel.exists)
}
}
XCUITest 通过 XCTWaiter 和 NSPredicate 谓词支持显式等待。例如,在 5 秒内等待元素出现:XCTWaiter().wait(for: [expectation], timeout: 5)。与 Detox 不同,XCUITest 没有与网络请求的自动同步。
// 等待元素出现带超时
let expectedElement = app.staticTexts["welcomeMessage"]
let existsPredicate = NSPredicate(format: "exists == true")
let expectation = XCTNSNotificationExpectation(object: expectedElement)
let result = XCTWaiter().wait(
for: [expectation], timeout: 5
)
XCTAssertEqual(result, .completed)
XCUITest 支持测试复杂场景:多点触控手势、推送通知、Deep Links、SFSafariViewController 和跨应用交互。Siri 意图也可以通过 XCUITest 使用 Siri Remote 模拟进行测试。
XCUITest 支持所有流行手势:tap、doubleTap、pressForDuration、swipeUp/Down/Left/Right、pinch、rotate、twoFingerTap。对于复杂场景,使用具有任意坐标和持续时间的 XCUIGesture。这允许测试自定义手势,如绘图或拖放。
从 Xcode 12 开始,XCUITest 通过 XCTestExpectation 和 URLProtocol 支持拦截网络请求。这使得可以在离线模式或使用替换的服务器响应来测试应用程序,而无需修改应用程序代码。
XCUITest 在 CI 环境中通过 xcodebuild 使用 test 标志运行。要在多个模拟器上并行运行,请使用 xcodebuild -testPlan 并在 Xcode scheme 中配置并行执行。GitHub Actions、Bitrise 和 Jenkins 具有对 XCUITest 的内置支持。
CI 需要配置 code signing、provisioning profiles 并指定目标(模拟器或设备)。模拟器上的 iOS 测试不需要证书。对于真实设备,需要通过 Xcode Cloud 或 Fastlane 进行自动签名。
# 通过 xcodebuild 在模拟器上运行 XCUITest
xcodebuild test \
-project MyApp.xcodeproj \
-scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 15,OS=17.5' \
-resultBundlePath ./TestResults \
-parallel-testing-enabled YES \
-parallel-testing-worker-count 4
XCUITest 与 Apple 的 Accessibility API 密切相关,因为元素搜索基于可访问性属性。可访问性测试 — 不仅是查找元素的方法,也是检查应用程序对残障人士的可访问性。XCUITest 可以检查 accessibilityLabel、traits 和 hints。
VoiceOver — Apple 为盲人用户提供的屏幕阅读器。XCUITest 允许检查:accessibilityLabel — 元素是否用可理解的文本描述,accessibilityTraits — 元素类型是否匹配(按钮、标题、图像),以及 accessibilityHint — 是否提供有关操作结果的提示。这些检查是发布到 App Store 所必需的,XCUITest 在回归运行中自动执行它们。
从 Xcode 15 开始,XCUITest 通过 XCTAttachment 支持内置的 Accessibility 检查,使用 accessibilityAudit 类型。测试会自动报告对比度不足的元素、未标记的图像和错误的 traits。这取代了手动 Accessibility Inspector。
// XCUITest 中的可访问性审核
func testAccessibilityAudit() {
let app = XCUIApplication()
app.launch()
let audit = XCTAttachment(accessibilityAudit: app)
add(audit)
// 检查特定元素
let button = app.buttons["submitButton"]
XCTAssertTrue(button.label.count > 0)
XCTAssertTrue(button.isAccessibilityElement)
}
XCUITest 通过 XCTOSSignpostMetric 和 XCUIApplication.metrics 支持 UI 性能测量。可以测量应用程序启动时间(launch time)、导航速度、对手势的响应时间。性能测试使用基线测量运行,并在超过阈值时自动失败。这可以防止性能回归在发布版本中到达用户之前发生。
基线 — 测试执行的参考时间。Xcode 会记住每个测试在特定设备型号和 iOS 版本上的基线。如果新执行超过基线一定百分比(默认为 10%),则测试被视为失败。要更新基线,请使用测试报告中的 Edit Baseline 命令。在更新 iOS 版本或更改 CI 农场的设备型号时,重新计算基线很重要。
用于跟踪 XCUITest 测试稳定性的标志:continueAfterFailure(首次失败后是否继续测试)和带有重试配置的 Xcode 测试计划。建议配置自动重启失败的测试(retry)——对于与动画时间或网络延迟相关的 flaky 测试,最多重试 3 次。
XCUITest 通过 springboard 和 launchArguments 支持推送通知和 Deep Links 测试。对于推送通知,使用带有 -UNUserNotificationCenter 参数的 XCUIApplication().launchArguments 并通过 XCTest 发送。Deep Links 通过使用自定义方案的 open URL 进行测试——XCUITest 拦截系统对话框并检查应用程序是否在正确的屏幕上打开。要测试对通知的响应场景,使用 XCUIApplication().springboard,它模拟在 iOS 通知中心点击通知横幅。这些场景对于具有深层链接和推送活动的应用程序至关重要,需要验证外部调用的正确处理。
对于详细的性能分析,XCUITest 与 Instruments 集成。在测试期间,可以通过 XCTMetric 启动 Time Profiler、Core Animation 或 Leaks 分析。分析结果保存在报告中,可在 Xcode 中进行分析。这在优化应用程序启动时间、屏幕间导航和动画性能时特别有用——这些是 iOS 应用程序中的典型瓶颈。
常见问题
XCTest 是所有 Apple 测试类型的通用框架,包括单元测试和性能测试。XCUITest 是 XCTest 之上的 UI 测试层,它添加了 XCUIApplication、XCUIElement 和 XCUIElementQuery 类用于与界面交互。
可以,XCUITest 同时支持 Swift 和 Objective-C。然而,Apple 的大多数示例和文档都是用 Swift 编写的。Objective-C 项目无需额外配置即可使用 XCUITest——该框架可通过 @import XCTest 访问。
XCUITest 使用 Apple 的 Accessibility API。元素通过 accessibilityIdentifier、accessibilityLabel、类型(button、textField、staticText)或层次结构中的位置找到。应用程序代码中设置的 Accessibility 属性越精确,测试就越稳定。
是的,Xcode 包含用于 UI 测试的内置录制器。在录制模式下运行测试时,Xcode 会记录所有与界面的交互并生成 Swift 代码。录制的代码可以改进:添加检查、提取到 Page Objects 和参数化。
要在真实设备上运行:将设备连接到 Mac,将其添加到 Apple Developer Program,配置 provisioning profile,使用开发证书签署应用程序,并在 xcodebuild 中选择设备作为目标。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。