Comprehensive Guide to iOS UI Automation Testing with XCUITest, Appium, and Web Service Architecture
This article provides a detailed overview of iOS UI automation testing, covering XCUITest fundamentals, accessibility considerations, code examples, manual and recorded test case creation, command‑line toolchains, Web Service‑based architecture, and a comparison of Appium and Macaca for building scalable, cross‑platform mobile testing platforms.
Introduction
The author, after a year at Trip.com, shares experiences and lessons learned from building and maintaining an iOS UI automation testing platform, outlining the article's structure and goals.
XCUITest Principles
Apple introduced XCUITest in 2015 as a UI automation framework integrated into Xcode. It relies on two core technologies: XCUITest and Accessibility . The Test App runs as a daemon, managed by XCUIApplication , which drives the Host App using element‑query APIs.
Accessibility only exposes elements readable by VoiceOver; developers must set isAccessibilityElement and related properties (e.g., accessibilityIdentifier ) for views like UIImageView or generic UIView to be visible to the testing engine.
Framework Structure
The XCUITest API includes element queries ( XCUIElementQuery ), UI elements ( XCUIElement ), and application lifecycle objects ( XCUIApplication ).
Demo Project
A simple demo creates four UI components (image view, label, view, button) with accessibility identifiers. The source code is shown below:
import UIKit
class ViewController: UIViewController {
lazy var testImageView: UIImageView = {
let testImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
testImageView.backgroundColor = .red
testImageView.accessibilityIdentifier = "test imageview"
return testImageView
}()
lazy var testLabel: UILabel = {
let testLabel = UILabel(frame: CGRect(x: 0, y: 130, width: 100, height: 20))
testLabel.backgroundColor = .green
testLabel.text = "test label"
return testLabel
}()
lazy var testView: UIView = {
let testView = UIView(frame: CGRect(x: 0, y: 170, width: 100, height: 50))
testView.backgroundColor = .blue
testView.accessibilityIdentifier = "test view"
return testView
}()
lazy var testButton: UIButton = {
let testButton = UIButton(frame: CGRect(x: 0, y: 230, width: 100, height: 50))
testButton.backgroundColor = .yellow
testButton.setTitle("测试按钮", for: .normal)
return testButton
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(testImageView)
view.addSubview(testLabel)
view.addSubview(testView)
view.addSubview(testButton)
}
}The demo explains how each view is instantiated and why accessibility identifiers are required for non‑standard UI elements.
Accessibility Inspector
Developers can use Xcode’s Accessibility Inspector (via Open Developer Tool → Accessibility Inspector ) to view the element hierarchy. Setting isAccessibilityElement = true makes previously hidden views appear in the hierarchy.
Manual Test Cases
import XCTest
class UITestDemoUITests: XCTestCase {
override func setUpWithError() throws { /* ... */ }
override func tearDownWithError() throws { /* ... */ }
func testExample() throws {
let app = XCUIApplication()
app.launch()
let label = app.staticTexts["test label"]
XCTAssertTrue(label.exists)
let button = app.buttons["测试按钮"]
XCTAssertTrue(button.exists)
let imgview = app.images["test imageview"]
XCTAssertTrue(imgview.exists)
let view = app.otherElements["test view"]
XCTAssertTrue(view.exists)
}
func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, *) {
measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch()
}
}
}
}The test launches the app, queries elements by their accessibility identifiers, and asserts their existence.
Recording Interaction
Xcode can record UI interactions to generate test code automatically, simplifying test creation for complex scenarios.
Command‑Line Toolchains
Various CLI tools enable scripting of UI tests for CI integration:
xcodebuild test -project UITestDemo.xcodeproj -scheme UITestDemoUITests -destination 'platform=iOS,id=<iPhoneUDID>'
Separate build and test commands using xcodebuild build-for-testing and xcodebuild test-without-building .
xcrun simctl for simulator management (list, boot, shutdown, install, launch, terminate, uninstall).
ideviceinstaller for real‑device app installation, removal, and listing.
ios-deploy for device connection, app install/uninstall, and bundle‑id checks.
These commands can be woven into Jenkins pipelines to achieve automated UI testing on both simulators and physical devices.
Web Service‑Based Architecture
The article describes a two‑layer architecture: a command‑dispatch Web Service (RESTful API) and a UI‑driver module. Test cases act as clients, sending HTTP requests to the server, which forwards them to platform‑specific drivers (e.g., Appium’s WebDriverAgent for iOS or XCTestWD for Macaca). The driver runs as a Test App, exposing its own Web Service to receive commands, execute actions, and return results.
Jenkins can host the command‑dispatch service, while multiple slaves run driver instances on various devices, enabling distributed, concurrent testing.
Appium Toolchain
Appium uses WebDriverAgent as its iOS driver. Installation steps include cloning the repository, configuring the development team, and launching the Appium server via GUI or CLI ( appium -a 127.0.0.1 -p 4722 ). Port mapping with iproxy is required for real devices.
Sample JavaScript WebDriverIO capabilities are shown:
const iosCaps = {
platformName: 'iOS',
automationName: 'XCUITest',
deviceName: process.env.IOS_DEVICE_NAME || 'iPhone',
udid: 'iphone udid',
platformVersion: process.env.IOS_PLATFORM_VERSION || '13.6.1',
noReset: true,
bundleId: 'your app id',
app: undefined // added in tests
};Tests are executed with npm test .
Macaca Toolchain
Macaca provides a similar stack (driver, Web Service server, client). Installation is via npm ( npm i macaca-ios -g ) and may require a development team ID.
Comparison
Framework
Similarities
Differences
Appium
Both rely on XCUITest and Accessibility for iOS UI automation
Appium driver is written in Objective‑C, has a larger community, and more frequent updates
Macaca
Both rely on XCUITest and Accessibility for iOS UI automation
Macaca driver is written in Swift, community is smaller and less active
The author’s platform initially used Macaca and is now gradually migrating to Appium for broader support and long‑term stability.
Trip.com App Automation Status
The platform supports three main scenarios:
Smoke testing : lightweight UI checks integrated into GitLab merge‑request pipelines; each run finishes within ~6 minutes.
Exploratory testing : white‑/gray‑box tests built on Google eDistantObject and EarlGrey, achieving high coverage without Accessibility limitations; 5 concurrent jobs can explore ~180 distinct pages in 2 hours.
Full UI automation platform : a Jenkins‑driven, multi‑machine system executing up to 209 test cases (≈3 000 steps) with >97 % feature pass rate and ~40 minute total runtime.
Conclusion
Apple’s core iOS UI automation technologies are XCUITest and Accessibility . Building on them, Web Service‑based platforms like Appium and Macaca provide cross‑platform, easily deployable, and highly reusable testing solutions that enable distributed execution and reduce manual effort.
Acknowledgments
The author thanks the Trip.com IBU Public Wireless team, especially leader Shanks, for mentorship and support.
References
闲话iOS探索测试实现 – https://shanks.pro/2020/05/16/ios-explore-test/
Testing with Xcode – User Interface Testing – https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/09-ui_testing.html
WWDC2015 UI Testing in Xcode – https://devstreaming-cdn.apple.com/videos/wwdc/2015/406o0doszwo8r15m/406/406_ui_testing_in_xcode.pdf?dl=1
WWDC2019 Testing in Xcode – https://devstreaming-cdn.apple.com/videos/wwdc/2019/413kpguqjv5fqp9/413/413_testing_in_xcode.pdf?dl=1
Accessibility and UI Testing in iOS – https://medium.com/@jchen_77520/accessibility-and-ui-testing-in-ios-3eb0822a17fb
UIAccessibility – https://developer.apple.com/documentation/objectivec/nsobject/uiaccessibility
iOS real‑device commands – https://www.cnblogs.com/xiyuan2016/p/9929814.html
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.