In this tutorial, you will learn about different ways of accessing UI elements when writing UI Tests in Xcode.
If you are interested in video lessons on how to write Unit tests and UI tests to test your Swift mobile app, check out this page: Unit Testing Swift Mobile App
Let’s assume we have this view with a Signup form details on it. This view has 5 UITextFields and a single button.
UIElement Groups
Below is a list of UI elements groups that you can use to refer to a specific UI element type in a UI Test method.
- app.alerts
- app.buttons
- app.collectionViews
- app.images
- app.maps
- app.navigationBars
- app.pickers
- app.progressIndicators
- app.scrollViews
- app.segmentedControls
- app.staticTexts
- app.tabBars
- app.tables
- app.textFields
- app.textViews
- app.webViews
Below are examples of how to use these groups to access an element by their index, static text, or an accessibility identifier.
When There is Single Element Only
If you know that you have a single button on the view, and there are no other buttons, then you can access it by using the following Query.
let signupButton = XCUIApplication().buttons.element
You create an instance of UI application, then refer to a list of all available buttons, and then, since there is only a single button, you can simply refer to it directly without specifying any static text or accessibility identifier. This will return a reference to a UIElement and you can start working with it.
let signupButton = XCUIApplication().buttons.element signupButton.tap()
When There is More Than One Element
If you have more than one element of the same type, then you will need to use a different approach. For example, in the Signup form that is on the image above, there are five UITextFields. To access a list of all available UITextField elements, we can use a special property called textFields. This will make a list of UITextField elements available to you.
let allTextFields = XCUIApplication().textFields
Accessing Elements By a Their Static Text
You can access a specific UI element by either using its static text placeholder or index in the list. In the below example, I am accessing the First name UITextField element by using its Placeholder text.
let firstNameTextField = XCUIApplication().textFields["First name"]
Once we have a reference to an element we can start interacting with it.
let firstNameTextField = XCUIApplication().textFields["First name"] firstNameTextField.tap() firstNameTextField.typeText("John")
I can also access the button by using its label.
let signupButton = XCUIApplication().buttons["Signup"] signupButton.tap()
Accessing Elements by Their Index
You can also access elements by their index. For example, in the image above there are five UITextFields. The very first UITextField will have an index 0, the second IUTextField will have an index 1, the next UITextField will have an index 2, and so on. Just like we access elements of an array by using their index.
let firstNameTextField = XCUIApplication().textFields.element(boundBy:0) let lastNameTextField = XCUIApplication().textFields.element(boundBy:1) let emailTextField = XCUIApplication().textFields.element(boundBy:2)
Although this way of access elements works well, it is not very reliable. If a new UI element is added in between, then the index of one of these elements will change and most likely your UI Test method will fail. Whenever possible we should access UI Elements by their accessibility identifier.
Accessing Elements with an Accessibility Identifier
As it was mentioned above, whenever possible we should try accessing elements in UI Test methods using their accessibility identifier. Accessibility identifier is like a unique id that you assign to a UI Element and then whenever you needed you can refer to this UI element by this id.
The problem with accessing elements using their static text is that this text can change. For example, a text on a UIButton label can change and a UILabel text can also change. If we refer to these UI elements by their static text and that text changes our UI test method will fail.
To set an accessibility identifier on a UI element programmatically is easy. Let’s assume we have a UITextField element on the view. Then to set an accessibility identifier on it the following way:
firstNameTextField.accessibilityIdentifier = "firstNameTextField"
To access the firstNameTextField UI element in the UI Test method I can then use its accessibility identifier the following way:
let firstNameTextField = XCUIApplication().textFields["firstNameTextField"]
Advanced Queries
Another way of locating UI elements is by using Advanced Queries, that allow us to locate all children or all descendants of an element in the view.
We can access direct subviews of an element by referring to its children.
XCUIApplication.scrollViews["thumbnails"].children(matching: .image)
If we need to look deeper and access sub-subviews, we can use descendants instead of children.
XCUIApplication.scrollViews["thumbnails"].descendants(matching: .image)
I hope this short tutorial was of some value to you. If you are interested in a step by step series of video lessons then have a look at my video course “Unit Testing and UI Testing Swift Mobile App“.
Happy Testing! 🙋🏻♂️