UITesting in Xcode 7

UITesting in Xcode 7

  • Developers writing apps for iOS9.
  • Written in Swift or Objective-C.

"It used to be a pain in the ass, but now, with the introduction of UIRecording it has become really easy."

  • Find & interact with UI elements, validate UI properties & state, perform asserts to check if UI elements behave correctly.
  • It used to be a pain in the ass, but now, with the introduction of UIRecording it has become really easy.
  • It’s useful to know that you didn’t break anything after making a change.

Fast road to success:

  1. Install XCode 7
  2. Add UI testing target (or when creating a new app check “include UI tests”)
  3. Go to the UI Testing folder that was created for you, open the test
  4. Put your cursor in the testExample
  5. Press record in the bottom left corner (app runs on simulator/device)
  6. Press the buttons you want to test
  7. Stop recording

You just created your first test! Well you’re not really checking anything are you? Other than checking wether buttons can be tapped, this doesn’t seem like a real test. Add asserts to check the state of your application.We can use XCTAssert to check some things, as we would in a regular Unit test:

  • Add a button to your storyboard and connect the IBAction
  • Press the button and the title will change to “selected”
class ViewController: UIViewController {
    @IBAction func buttonPressed(sender: UIButton) {
        button.selected = !button.selected
        button.setTitle(sender.selected ? "selected" : "normal", forState: UIControlState.Normal)
    }
}
  • Automate the UITesting and perform assertions
  func testNotSelected() {
        let element:XCUIElement =  XCUIApplication().buttons.elementBoundByIndex(0)
        XCTAssertEqual(element.label, "normal")
    }

    func testSelected() {
        let element:XCUIElement = XCUIApplication().buttons.elementBoundByIndex(0)
        element.tap()
        XCTAssertEqual(element.label, "selected")
    }

Ok so now we’ve created our first UITest. It might come in handy to actually know what we are doing, so in the following section we’ll get to know the new UITesting api a bit more.XCUIApplication is a proxy for your tested application. You have control over launch & termination of your application. Every time you call launch, a new process is spawned.To test your application you might want to tap around and give some user input, which comes in the form of events. Here are two examples of how you can trigger an event:

Perform a tap:

 - button.tap()

Type in a textfield:

 - textfield.typeText(“hello world”)

To be able to trigger an event, we must find the right element, for example the button we want to tap on. Finding the right elements can be done using an XCUIElementQuery.This query gets a collection of accessible elements.

To get more information about this collection, we can perform operations on it:

  • count
  • subscripting
  • elementBoundByIndex()

Relationships can help us find the element we are looking for:

  • descendants (ex: a view with all its subviews => on all levels)
  • children (ex: cells in a tableView => 1 level subviews)
  • containment (ex: a button in a view)

You can also perform queries by filtering on:

  • type
  • identifier
  • predicates (value, partial matching,…)

Examples:

  • view.descendantsMatchingType(.Button): This can be shortened by using the convenience method: .Buttons, and will give you an array of all the buttons in that view (and it will go trough all the descendants of that view).
  • tableView.childrenMatchingType(.Cell): Gives you the children of that tableView of the type Cell, this will only go 1 level deep.
  • cells.containgType(.StaticText, identifier:”Groceries”): Returns you a list of cells which contain a descendant of the type StaticText and have “Groceries” set as identifier.

All the elements on the screen are queried as XCUIElements. Most of the time elements can be found by a combination of their type and an identifier.

  • Types of elements: Button, Cell, Window
  • Identifiers you can use: Accessibility identifier, label, title,…
  • What you can check on an XCUIElement is rather limited. Checking whether an image is set on a UIButton seems not possible, and something simple as checking the background color can not be done yet…
  • The focus of UITesting with Xcode 7 will be more on checking whether the flow of your app can be completed, rather than checking every little detail.
  • Another limitation is the complete lack of documentation and coding samples, the links in the WWDC presentation never worked. You can find some unofficial documentation here: https://github.com/joemasilotti/XCTest-Documentation