Skip to content
master
Go to file
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 

README.md

UI Testing UI Testing Example

This sample project shows a different approach to writing UI tests that has a number of benefits:

  • 👩🏻‍🏫 Easier to read
  • 👨🏾‍🔧 Easier to maintain
  • 👩🏼‍💻 Easier to write tests first

Overview

UI Testing Process

When implementing a new feature, ideally, you will follow a three-step process:

  1. Write test page objects (see Test Page)
  2. Write failing UI tests (see UI Tests)
  3. Implement feature, making tests pass

Test Page

UI Test Page

A test page object is typically comprised of three parts:

  1. Elements
  2. Actions
  3. Verifications

These sections represent a screen in your app. The elements are private to the page object, and the actions and verifications are the API surface for UI tests to use in validating the behavior of the app.

An element may look something like:

fileprivate var table: XCUIElement {
    return app.tables["MasterViewController.tableView"]
}

An action is going to return the test page object that is the result of the action, and might look like this:

@discardableResult func tapOnCell(at index: Int, file: String = #file, line: UInt = #line) -> DetailPage {
    let cell = self.cell(at: index)
    testCase.expect(exists: cell, file: file, line: line)
    cell.tap()
    return DetailPage(testCase: testCase)
}

Note: We use custom functions instead of XCTAssert to make the testing code more readable. View more in Matchers.swift.

Finally, a verification is a function to use in validating the expected state of the app, and may look like this:

@discardableResult func verifyTableCellCount(is count: Int, file: String = #file, line: UInt = #line) -> MasterPage {
    testCase.expect(exists: table, file: file, line: line)
    testCase.expect(table.cells.count, equals: count, file: file, line: line)
    return self
}

UI Tests

UI Tests

In the actual UI tests, which are written in a subclass of XCTestCase, you will create a test page object, and call various functions on that object. These tests are exceptional readable, and make it much easier to reason about the behavior that you are expecting as users interact with your app.

An example test for verifying an entry can be added and viewed properly may look like this:

func testAddingEntry() {
    let zeroLabel = "0" 
    
    MasterPage(testCase: self)
        .verifyMasterPageIsShowing()
        .verifyTableCellCount(is: 0)
        .tapOnAddButton()
        .verifyTableCellCount(is: 1)
        .verifyCell(at: 0, hasLabel: zeroLabel)
        .tapOnCell(at: 0)
    
        // Detail page
        .verifyDetailPageIsShowing()
        .verifyLabelText(is: zeroLabel)
        .tapOnBackButton()
    
        // Master page
        .verifyMasterPageIsShowing()
}

Summary

This approach to UI testing has led to significant improvements in our tests and the time it takes to write and maintain them. Hopefully this is helpful to you as well!

About

Sample project using Apple's Master-Detail App template to demonstrate UI testing

Resources

License

Releases

No releases published

Packages

No packages published

Languages

You can’t perform that action at this time.