How To Use XCUITest API

How to Use XCUITest API

So far we have covered most of the topics around setting up XCUITest framework and making it scalable and maintainable. However, we haven’t covered the XCUITest API and the other features of XCUITest framework that we can use in our iOS app testing. In this post, we will cover the basics of XCUITest API and how to utilize those API to write UI tests for iOS apps.

XCUITest API

Apple announced the Xcode UI Testing which covers most of the underlying architecture of the XCUITest framework. It’s highly recommended that one should watch this session until the end to understand the XCUITest API in detail. In summary, XCUITest has three main classes:

This class is responsible for launching the app under test. Since Xcode 9, we can also perform multi-app testing as well.

This class is responsible for finding elements in the view using different types of queries. The query should return a unique UI element.

This class is responsible for UI elements and perform some actions on the UI elements.

These are the basic classes provided by the XCUITest framework. Now, we will see some examples of how to use those API.

Launching/Terminating App

If we want to launch/terminate the target app which is the main app, we can easily do that using the launch or terminate method. 

XCUIApplication().launch()
XCUIApplication().terminate()

If we want to launch an app with certain launch arguments or launch environments that have been set up in the main app. e.g we can launch an app with LaunchArgument asUITest using thelaunchArguments method. 

XCUIApplication().launchArguments = ["UITest"]

Similarly, we can launch an app with launch environments as below 

XCUIApplication().launchEnvironment = ["UITest": "NO"]

The only difference between launchArgument & launchEnvironment is that the argument is the array of parameters and the environment is a dictionary passed to them. You can read more about the Launch Arguments and Launch Environments here

Launch Different App

Since Xcode 9, we can launch a different app, if we have a bundle identifier of the app. If you want to launch Safari app, for example, then you can do that using

XCUIApplication(bundleIdentifier: "com.apple.mobilesafari").launch()

Find UI Elements 

While writing XCUITest tests for iOS apps, it’s important to find an element in the view. We have to use XCUIElementQuery to find the unique element on the page. There are different techniques to reach the unique element. The most common one is Subscripting. If we want to find all the buttons in the current view, for example, we can print out all the buttons using XCUIApplication().buttons but if you want to access with the Search identifier, then we have to use subscript like this 

XCUIApplication().buttons["Search"]

This is applicable for other UI elements like Static Text, Collections Views etc. There are other techniques to find elements using predicates and indexes mentioned in the official API here.

Determine State Of the Element 

Once we’ve found the UI Element using the abovementioned query, the next step would be determining the state of the element or perform some action on it. We can easily check if the element exists in the view hierarchy using exists method as below. 

XCUIApplication().buttons["Search"].exists

This method will return boolean depending on the existence of the button in the view hierarchy. There are other properties that we can verify like if the element is hittable or enabled etc.

While asynchronous UI tests are under execution, we have to wait for the UI element to appear on the screen. We can easily wait for the element to appear on the screen using the waitForExistance method on the UIElement. When we tap on the Search button, for instance, then search results will take some time to load. We can wait for the Search Results using 

XCUIApplication(). StaticText["Search Result"].waitForExistance(timeout: 5)

This will return true if search results appear in 5 seconds. 

Perform Action On the Element 

The XCUITest API gives loads of options to perform actions on the XCUIElement if the state of the UI element is actionable. There are various methods with different actions are available as part of the XCUIElement class. For example, we can tap on the element using tap method 

XCUIApplication().buttons["Search"].tap()

There are various other API available to perform the other actions like typing the text in the text field, swipe up, swipe down, pinch, adjust the picker wheel value etc. If you want to know more about different options, there is an excellent blog post UI testing Cheat Sheet with examples here

Asserting the UIElement

In most of the cases, there is no need to add explicit assertions while finding elements or performing an action on the UI elements. The test will fail automatically if the expected UI element not found on the screen. However, in some cases, we need to add some explicit assertions. Apple has provided XCTAssert and XCTAssertTrue macro to check if the state of the UI element is as expected. For example, we can assert that the Search button exists or not using 

XCTAssertTrue(XCUIApplication().buttons["Search"].exists)

The assertion will fail if there isn’t any Search button in the existing view. 

Now we have covered the basics of the XCUITest API and how we can use those API in our existing apps. Though it’s hard to cover each method in a post, we have touched all the basic methods – those are commonly used in the XCUITest scripting. If you want to try it out on iOS devices in the cloud, you can check out what Bitbar Testing has to offer.

Conclusion 

Apple’s XCUITest framework provides convenient API so that test developers can write clean and concise tests for their apps. Test developers just need to understand and explore the XCUITest API and use them effectively in their workflow.


An Essential Guide to XCTest Framework for iOS App Testing

Get all essentials about XCTest framework and learn how to get started with it for cloud testing

Download