XCode is bundled with fairly sophisticated UI testing capabilities, but doesn’t provide the best documentation or most intuitive interface. Here, I’ll list a few tips that I’ve been saving and referencing when creating UI tests.
How-To Resources
A number of excellent write-ups and resources already exist. Many of the tips below originated in these:
Accessibility and UI Testing in iOS by Jonathan Chen
• https://medium.com/@jchen_77520/accessibility-and-ui-testing-in-ios-3eb0822a17fb
⁃ Well-written, detailed descriptions of how UI testing works in iOS and its relation to accessibility
Xcode UI Testing Cheat Sheet by Paul Hudson
• https://www.hackingwithswift.com/articles/148/xcode-ui-testing-cheat-sheet
⁃ Great list of elements and queries with concise examples. Also tips for communicating between the tests and app
UI Testing Cheat Sheet and Examples by Joe Masilotti
• http://masilotti.com/ui-testing-cheat-sheet/
⁃ Solid examples of how to manipulate trickier controls like slider and picker in testing. Slightly dated
Quick Tips
There are a number of XCUIElement selectors, but a particular subset is most common:
XCUIElement | Corresponding UIKit class |
.button | UIButton, including in tab bars, navigation bars, and alert modals |
.staticText | UILabel, including pretty much any text |
.other | UIView |
.cell | UICollectionViewCell and UITableViewCell |
Queries:
.exists .isHittable
Waiting (synchronously / blocking):
sleep(3) // wait 3 seconds
element.waitForExistence(3) // waits for at-most 3 seconds but continues as soon as true
Performing actions:
.tap() .typeText("foo") .rotate()
Getting elements by order:
let app = XCUIApplication() app.buttons.element(boundBy: 0) // gets the first button on screen app.buttons.element(boundBy: 3) // gets the fourth
View all the UITest labels and elements onscreen (the Accessibility Hierarchy):
print(app.debugDescription)
Assert a button is onscreen:
let window = app.windows.element(boundBy: 0) let element = app.buttons.element(boundBy: 0) XCTAssert(CGRectContainsRect(window.frame, element.frame))