How to Use XCUITest API
In this post, we will cover the basics of XCUITest API and how to utilize those API to write UI tests for iOS apps.
Join the DZone community and get the full member experience.
Join For FreeSo far, we have covered most of the topics around setting up the 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 as UITest
using the launchArguments
method.
Similarly, we can launch an app with launch environments as below
The only difference between launchArgument
and 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 waitForExistence 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"].waitForExistence(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 a 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.
Published at DZone with permission of Shashikant Jagtap, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments