DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Securing Your Software Supply Chain with JFrog and Azure
Register Today

Trending

  • SRE vs. DevOps
  • Deploying Smart Contract on Ethereum Blockchain
  • What ChatGPT Needs Is Context
  • Integrating AWS With Salesforce Using Terraform

Trending

  • SRE vs. DevOps
  • Deploying Smart Contract on Ethereum Blockchain
  • What ChatGPT Needs Is Context
  • Integrating AWS With Salesforce Using Terraform

Tips for Writing Scalable XCUITests - WWDC 2017

Fresh from a WWDC talk on testability, these tips for writing more scalable tests for iOS apps can help make your tests faster and more readable.

Shashikant Jagtap user avatar by
Shashikant Jagtap
·
Jul. 18, 17 · Tutorial
Like (1)
Save
Tweet
Share
3.69K Views

Join the DZone community and get the full member experience.

Join For Free

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

What Is Scalable Test Code?

The test code is as important as the app code even though it's not being executed in production. We should definitely make our app testable, but also put some effort into making the test code more scalable. The benefits of scalable test code are

  • Running our tests faster.
  • Making our tests more readable, even for non-technical people.
  • Organizing the test code in a better way to avoid duplication.
  • Making 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 an example application, Scalable-XCUITest. This app has buttons with six different colors: RED, GREEN, BLUE, BLACK, GRAY, and YELLOW. This is a very simple app, but imagine that we have to test a few things, like

  • Tapping on all the colors.
  • Just tapping on RBG colors.
  • Tapping on non-RBG colors.

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.swifthere 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 Tests

Here 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 through some of these techniques.

Abstract Xcuielement Query

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

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

Now we can just pass the name of the color to the method. We can go even further and store each element of the color 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 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()
    }
}

Our test will look like this:

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

Encapsulate Common Testing Workflows

We now have to test for the specific colors. We can also define Swift enumerations for RGB and non-RGB color 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 colors 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 our test to tap on RBG and non-RBG buttons is more readable and extendable.

Sprinkle Xctactivities for Better Test Reporting

Activities are a way to organize actions into groups by giving a meaningful name so XCTest results will use that activity name in the result, making it more readable. You can read more about activities in Apple's official documentation here. In our example, we can sprinkle in XCTActivities and make more readable 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 It Yourself

You can try these tips yourself with the example project on GitHub, Scalable-XCUITest with Xcode 9.

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

I 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!

Testing

Published at DZone with permission of Shashikant Jagtap, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • SRE vs. DevOps
  • Deploying Smart Contract on Ethereum Blockchain
  • What ChatGPT Needs Is Context
  • Integrating AWS With Salesforce Using Terraform

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: