Tips for Writing Scalable XCUITests — WWDC 2017

Shashikant Jagtap
XCBlog
Published in
4 min readJul 4, 2017

At WWDC 2017, there was an amazing talk on engineering for testability which focuses on importance of quality of test code along with app code. The talk introduced various way we can improve testability of apps by writing great test code. The most important bit was second part where the tips on improving scalability of UI tests has been shared. In this post, we will see what are those tips shared by Apple engineers. Remember, this is not just copy paste of the talk presented at WWDC, this post also has some real life examples with demo project on Github Scalable-XCUITest to prove those points.

WTF is Scalable Test Code ?

The test code is as important as app code even it’s not being executed in the production. We should definitely make our app testable but also put some efforts to make test code more scalable. So, the benefits of scalable test code are

  • Run our test faster
  • Make our tests more readable even for non-technical people
  • Organise test code in better way to avoid duplication
  • Make it easy to add new test cases

Example App

Let’s explore some of the techniques shared by Apple engineers to make the test code scalable with example application Scalable-XCUITest, this app has buttons with 6 different colours which are RED, GREEN, BLUE, BLACK, GRAY and YELLOW. This is very simple app but imagine that we have to test few things like

  • Tapping on all colours
  • Just tap on RBG colours
  • tap on non-RBG colours.

The non-scalable UI test for this looks something like this:

func testTapAllColorNonScalable() {
XCUIApplication().buttons["RED"].tap()
XCUIApplication().buttons["BLUE"].tap()
XCUIApplication().buttons["GREEN"].tap()
XCUIApplication().buttons["BLACK"].tap()
XCUIApplication().buttons["YELLOW"].tap()
XCUIApplication().buttons["GRAY"].tap()
}

Again to test the RGB and non-RGB values we have to almost repeat the same things. You can have a look at the test class Non_Scalable_XCUITestUITests.swift here and guess how messy it is. We can definitely make it better by using the techniques described in the talk.

Tips for Writing Scalable XCUITest

There are some tips shared to make tests scalable, maintainable and faster by using some common object oriented principles like abstraction and encapsulation. Let’s go though some of the techniques

Abstract XCUIElement Query

If there is situation where we are using XCUIElement query multiple time, store it as a variable. In the example above, we are tapping button 6 time but only thing changing is colour of the button. We can easily wrap this into the method.

func tapButton(_ color: String) {
XCUIApplication().buttons[color].tap()
}

Now that, we can just pass the name of the colour to the method. We can go even further and store each element of the colour in an array and loop through them.

func testTapAllColor() {
let colors = ["RED", "BLUE", "BLACK", "GREEN", "GRAY", "YELLOW"]
for color in colors {
tapButton(color)
}
}

Now that test looks more maintainable and readable.

Create Objects and Utility Function

We can go further and create a Colors class and store all the data inside the class as static members. We can the access those members from the tests.

class Colors {
static let colors = ["RED", "BLUE", "BLACK", "GREEN", "GRAY", "YELLOW"]
static func tapButton(_ color: String) {
XCUIApplication().buttons[color].tap()
}
}

We can the access those members from the tests. Our test will looks like this

func testTapAllColor() {
for color in Colors.colors {
Colors.tapButton(color)
}
}

Encapsulate Common Testing Workflows

We now have to test for the specific colours. We can also define Swift enumerations for RGB and non-RGB colour values.

enum RBG: String {
case red = "RED"
case blue = "BLUE"
case green = "GREEN"
}
enum Non_RBG: String {
case black = "BLACK"
case gray = "GRAY"
case yellow = "YELLOW"
}

We can access the raw values of the RGB and non-RGB colours from anywhere. We can now add more utility functions to our Colors class.

static func useRGB(_ rgb: RBG) {
XCUIApplication().buttons[rgb.rawValue].tap()
}

static func useNonRGB(_ nonRgb: Non_RBG) {
XCUIApplication().buttons[nonRgb.rawValue].tap()
}

We can call those configuration utility methods inside the test.

func testRBGBlueButton() {
Colors.useRGB(.blue)
Colors.useRGB(.red)
Colors.useRGB(.green)
}

Now that our test to tap on RBG and non-RBG button makes more readable and extendable.

Sprinkle XCTActivities for better test reporting

Activities is the way to organise those actions into group by giving meaningful name so XCTest result will use that activity name in the result to make it more readable. You can read more about activities on Apple official documentations here. In our example we can sprinkle an XCTActivities and make our more readable in the test reports.

func testRBGBlueButton() {
XCTContext.runActivity(named: "Check only RGB Colors") { _ in
Colors.useRGB(.blue)
Colors.useRGB(.red)
Colors.useRGB(.green)
}
}

You can see the entire test class Scalable_XCUITestUITests.swift on github here.

Try Yourself

You can try those tips yourself with example project on Github Scalable-XCUITest with Xcode 9.

$ git clone https://github.com/Shashikant86/Scalable-XCUItest
$ cd Scalable-XCUItest
$ open Scalable-XCUITest.xcodeproj

Hope you are already using the Swift abstractions and encapsulations to make XCUITests more scalable and maintainable, what are your experiences with XCUITests so far? Share in the comments below !

Like this post from XCBlog By XCTEQ ? You may also like some of our services like guest blogging or Mobile DevOps(CI/CD) or Test Automation. Chekout our services, open source projects on Github or Follow us on Twitter , Facebook, Youtube , LinkedIn. Download Our XCBlog iOS App to read the blogs offline.

XCTEQ Limited: Mobile DevOps, CI/CD and Automation

XCTEQ is a company specialised in Mobile DevOps, CI/CD, Mobile, AI/ML based Test Automation Checkout XCTEQ products and services at http://www.xcteq.co.uk or write to us on info@xcteq.co.uk..

--

--

XCBlog
XCBlog

Published in XCBlog

P.S: All the posts from this publication are published before author Shashikant Jagtap joined Apple. Thank you so much for being a reader of XCBlog. Tech Blog about DevOps, CI/CD for  Platforms. Xcode Server, XCTest, SwiftPM, Server Side Swift, XCUITest etc.

Shashikant Jagtap
Shashikant Jagtap

Written by Shashikant Jagtap

All the posts published on this channel before I joined Apple. Thanks for being a reader of XCBlog. Web: shashikantjatap.net, xcteq.co.uk