UI Testing Cheat Sheet and Examples.

Overview

UI Testing Cheat Sheet

This repository is complementary code for my post, UI Testing Cheat Sheet and Examples. The post goes into more detail with example images for most examples.

The included project highlights working code with a simple Test Host. This was last updated for Swift 5 on Xcode 11.4.1.

Contents

Basic Functionality

Testing if an element exists

XCTAssert(app.staticTexts["Welcome"].exists)

Testing if text with an ellipsis exists

A full text match will find an element even if the displayed text has an ellipsis due to truncation.

let longNameCell = app.staticTexts["Adolph Blaine Charles David Earl Frederick Gerald Hubert Irvin John Kenneth Lloyd Martin Nero Oliver Paul Quincy Randolph Sherman Thomas Uncas Victor William Xerxes Yancy Wolfeschlegelsteinhausenbergerdorff, Senior"]
XCTAssert(longNameCell.exists) // displayed text is "Adolph Blaine Charles David Earl Freder..."

Waiting for an element to appear

"Waiting" is now built into XCTest.

let goLabel = app.staticTexts["Go!"]
XCTAssertFalse(goLabel.exists)

app.buttons["Ready, set..."].tap()
XCTAssert(goLabel.waitForExistence(timeout: 5))

Interacting with System Controls

Tapping buttons

Identify buttons by their accessibility label.

app.buttons["Add"].tap()

Typing text

First make sure the text field has focus by tapping on it.

let textField = app.textFields["Username"]
textField.tap()
textField.typeText("joemasilotti")

Dismissing alerts

app.alerts["Alert Title"].buttons["Button Title"].tap()

Dismissing action sheets

app.sheets["Sheet Title"].buttons["Button Title"].tap()

Handling system alerts

Present a location services authorization dialog to the user and dismiss it with the following code.

Before presenting the alert add a UI Interruption Handler. When this fires, dismiss with the "Allow" button.

Bool in alert.buttons["Allow"].tap() return true } app.buttons["Request Location"].tap() app.tap() // need to interact with the app again for the handler to fire ">
addUIInterruptionMonitor(withDescription: "Location Services") { (alert) -> Bool in
  alert.buttons["Allow"].tap()
  return true
}

app.buttons["Request Location"].tap()
app.tap() // need to interact with the app again for the handler to fire

Sliding sliders

This will slide the value of the slider to 70%.

app.sliders.element.adjust(toNormalizedSliderPosition: 0.7)

Interacting with pickers

A picker with one wheel:

app.pickerWheels.element.adjust(toPickerWheelValue: "Picker Wheel Item Title")

A picker with multiple wheels. Make sure to set the accessibility delegate so the framework can identify the different wheels.

let firstPredicate = NSPredicate(format: "label BEGINSWITH 'First Picker'")
let firstPicker = app.pickerWheels.element(matching: firstPredicate)
firstPicker.adjust(toPickerWheelValue: "first value")

let secondPredicate = NSPredicate(format: "label BEGINSWITH 'Second Picker'")
let secondPicker = app.pickerWheels.element(matching: secondPredicate)
secondPicker.adjust(toPickerWheelValue: "second value")

Tapping links in web views

app.links["Tweet this"].tap()

Interactions

Verifying the current controller's title

XCTAssert(app.navigationBars["Details"].exists)

Reordering table cells

If you have a UITableViewCell with default style and set the text to "Title", the reorder control's accessibility label becomes "Reorder Title".

Using this we can drag one reorder control to another, essentially reordering the cells.

let topButton = app.buttons["Reorder Top Cell"]
let bottomButton = app.buttons["Reorder Bottom Cell"]
bottomButton.press(forDuration: 0.5, thenDragTo: topButton)

XCTAssertLessThanOrEqual(bottomButton.frame.maxY, topButton.frame.minY)

Pull to refresh

Create a XCUICoordinate from the first cell in your table and another one with a dy of six. Then drag the first coordinate to the second.

let firstCell = app.staticTexts["Adrienne"]
let start = firstCell.coordinate(withNormalizedOffset: (CGVectorMake(0, 0))
let finish = firstCell.coordinate(withNormalizedOffset: (CGVectorMake(0, 10))
start.press(forDuration: 0, thenDragTo: finish)

Pushing and popping view controllers

Test if a view controller was pushed onto the navigation stack.

app.buttons["More Info"].tap()
XCTAssert(app.navigationBars["Volleyball?"].exists)

Pop a view controller by tapping the back button in the navigation bar and assert that the title in the navigation bar has changed.

app.navigationBars.buttons.elementBoundByIndex(0).tap()
XCTAssert(app.navigationBars["Volley"].exists)
Comments
  • Simulate a Double Press on Home Button

    Simulate a Double Press on Home Button

    I'm trying to simulate double pressing the home button to launch the so-called app switcher. However, it looks like - (void)pressButton:(XCUIDeviceButton)button; is not synchronous and calling

    
    [[XCUIDevice sharedDevice] pressButton:XCUIDeviceButtonHome];
    
    

    would launch the home screen any way regardless of how quick the subsequent press follows. Any idea or tips on how to accomplish this?

    opened by jochasinga 9
  • How to search for element using regular expression?

    How to search for element using regular expression?

    Hi, for example, I know there will be a label named "This belongs to [someone]". The [someone] text will be dynamic, I know that there will be only one, how to find this label?

    opened by onmyway133 5
  • How to test specific view controller

    How to test specific view controller

    It seems all of the tests you write must start from the beginning, I want to write a class for testing specific view controller, without any action on another screen, Is there any solution?

    opened by hamedaakhlaghi 3
  • Finding Search Bar embedded inside a navigation bar in iOS 11.

    Finding Search Bar embedded inside a navigation bar in iOS 11.

    This repo has been exceptionally helpful. Thanks for making this.

    I've been running into a pickle especially while testing search on VCs in iOS 11 where the search bar is embedded inside a navigation bar. Neither app.searchFields or any child element under app.navigationBar reveal the relevant XCUIElement.

    Is there a workaround for this?

    opened by n0shake 3
  • Fixed testRefreshControl()

    Fixed testRefreshControl()

    #15 This is done by adding more offset to the drag position. This makes app to drag table more to the bottom which then makes progress disappear. Progress was blocking UI thread thus making lock state.

    opened by jakovljevic-mladen 2
  • Swift 3 migration

    Swift 3 migration

    The migration is complete 😄, but two tests are broken and I can't figure out what's wrong with them, so sending this over hoping it's just an easy thing that I overlooked.

    I made the commits as atomic as possible, tackling pre-migration warnings before the actual Xcode8 migration.

    There are many Storyboard changes, but functionality didn't change, Xcode forces you to select a device and update the views to reflect that viewport.

    opened by leopic 2
  • Question - Do you have a version for Xcode 8 and Swift 3

    Question - Do you have a version for Xcode 8 and Swift 3

    Hi Joe,

    Thank you for your great UI Testing Cheat Sheet. I am trying to converting it to Xcode 8 but failed with many error in syntax.

    Do you have a version of this app for Xcode 8 and Swift 3 ready? If yes, could you share it.

    Thanks again, Dat

    opened by ngtandat 2
  • Localization

    Localization

    I'm working on using Fastlane:Snapshot, and this projects is a great guide. But I am wondering how to target alerts in different languages when the text or button text isn't the same. IE, app.alerts["You won!"].buttons["Awesome!"].tap() or addUIInterruptionMonitorWithDescription("Location Services") { (alert) -> Bool in alert.buttons["Allow"].tap() return true } Especially considering the system alert buttons might not be the same translation even if I have NSLocaliazedString...

    opened by JamaicanRumCream 2
  • Question - Does the DismissingASystemAlert work on an actual device or just the simulator

    Question - Does the DismissingASystemAlert work on an actual device or just the simulator

    I was using your example and it works great on the simulator but I am not able to get the alert to be dismissed on an actual iPad Air 2 device. I think I remember reading somewhere that alerts are not being dismissed on ipad devices - only phones.

    opened by joykrogers 2
  • Question - Do you run all of the tests at one time or run them individually

    Question - Do you run all of the tests at one time or run them individually

    Thanks so much for the information you provide on UI Testing and XCode 7. I have found it very useful in helping me learn how to write UI Tests.

    I have seen several notes that tests should be stand alone. I downloaded this Volley project and if I run the tests individually - one at a time, they all work. But If I try to run all of them starting at the top, only one or two of them will pass.

    So would it be better to run the tests one at a time in general?

    Thanks

    opened by joykrogers 2
  • Webview Test Elements

    Webview Test Elements

    Hello! I think it's not the best place to ask this question but I was trying to figure out the issue. I was testing (XCUITest) a Webview (Load an Angular Page). I ran the test with this code line:

    let propertiesButton = app.webViews.otherElements.element(boundBy: 3).firstMatch if propertiesButton.exists { propertiesButton.tap() }

    Properties Window opened fine only in Simulator iPhone 11 - 13.1. If I run the same test with another Simulator like iPhone 11 Pro - 13.1 or 13.3 the tap() doesn't work.

    Also this line: app.swipeUp() when the Properties Window is opened, only works in Simulator iPhone 11 - 13.1

    I'm not sure if the issue will be from how the web view render the Angular page (CSS). Does anybody have or had the same issue?

    opened by bichoec 1
Owner
Joe Masilotti
Independent developer who's passionate about clean, testable code.
Joe Masilotti
SwiftCheck is a testing library that automatically generates random data for testing of program properties

SwiftCheck QuickCheck for Swift. For those already familiar with the Haskell library, check out the source. For everybody else, see the Tutorial Playg

TypeLift 1.4k Dec 21, 2022
Testing the UI without UI Testing, a Swift experiment.

UI tests without UI Testing experiment This repo is a small experiment to see if there's an "in-between" for testing iOS applications. More feature-le

Joe Masilotti 20 Sep 26, 2022
Swift Package with examples of how to tests iOS apps

GimmeTheCodeTDD A swift package with examples of unit tests in iOS development. Requirements Xcode 13 Content Dependency Injection Constructor Injecti

Dominik Hauser 8 Oct 11, 2021
Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running in minutes. @buildasaur

Buildasaur Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running

Buildasaurs 774 Dec 11, 2022
Implementing and testing In-App Purchases with StoreKit2 in Xcode 13, Swift 5.5 and iOS 15.

StoreHelper Demo Implementing and testing In-App Purchases with StoreKit2 in Xcode 13, Swift 5.5, iOS 15. See also In-App Purchases with Xcode 12 and

Russell Archer 192 Dec 17, 2022
I built this application with unit testing and test-driven development to understand TDD theory and practice

TestDrivenDevelopment Description I built this application with unit testing and test-driven development to understand TDD theory and practice, to wri

null 1 Dec 21, 2021
A flexible mock server for automated and regression testing of iOS, Android and other apps.

Note: This document is intended as a quick introduction to Voodoo. As Voodoo has a large number of features, please refer to Voodoo's Github Wiki for

Derek Clarkson 7 Nov 23, 2022
The Swift (and Objective-C) testing framework.

Quick is a behavior-driven development framework for Swift and Objective-C. Inspired by RSpec, Specta, and Ginkgo. // Swift import Quick import Nimbl

Quick 9.6k Dec 31, 2022
Snapshot testing tool for iOS and tvOS

SnapshotTest is a simple view testing tool written completely in Swift to aid with development for Apple platforms. It's like unit testing for views.

Pär Strindevall 44 Sep 29, 2022
A Mac and iOS Playgrounds Unit Testing library based on Nimble.

Spry Spry is a Swift Playgrounds Unit Testing library based on Nimble. The best thing about Spry is that the API matches Nimble perfectly. Which means

Quick 327 Jul 24, 2022
Multivariate & A/B Testing for iOS and Mac

This library is no longer being maintained. You can continue to use SkyLab in your projects, but we recommend switching another solution whenever you

Mattt 792 Dec 15, 2022
Remote configuration and A/B Testing framework for iOS

MSActiveConfig v1.0.1 Remote configuration and A/B Testing framework for iOS. Documentation available online. MSActiveConfig at a glance One of the bi

Elevate 78 Jan 13, 2021
Runtime introspection and unit testing of SwiftUI views

ViewInspector ??️‍♂️ for SwiftUI ViewInspector is a library for unit testing SwiftUI views. It allows for traversing a view hierarchy at runtime provi

Alexey Naumov 1.5k Jan 8, 2023
Swifty tool for visual testing iPhone and iPad apps. Every pixel counts.

Cribble Cribble - a tool for visual testing iPhone and iPad apps. Every pixel counts. Getting Started An example app is included demonstrating Cribble

Max Sokolov 273 Nov 4, 2022
Sample project for testing out focus in SwiftUI and iOS 15

This project was to test out different ways of enabling focus in a SwiftUI app.

null 3 Dec 21, 2021
T - A simple testing framework using closures and errors

t Quickly test expectations What is t? t is a simple testing framework using clo

OpenBytes 6 Nov 7, 2022
Network testing for Swift

DVR DVR is a simple Swift framework for making fake NSURLSession requests for iOS, watchOS, and OS X based on VCR. Easy dependency injection is the ma

Venmo 650 Nov 3, 2022
Mockingbird was designed to simplify software testing, by easily mocking any system using HTTP/HTTPS

Mockingbird Mockingbird was designed to simplify software testing, by easily mocking any system using HTTP/HTTPS, allowing a team to test and develop

FARFETCH 183 Dec 24, 2022
Fastbot is a model-based testing tool for modeling GUI transitions to discover app stability problems

Fastbot is a model-based testing tool for modeling GUI transitions to discover app stability problems. It combines machine learning and reinforcement learning techniques to assist discovery in a more intelligent way.

Bytedance Inc. 446 Dec 29, 2022