Logo for tanaschita.com

Getting started with UI Testing for SwiftUI

Learn how to create user interface tests with the XCTest framework.

30 Dec 2024 · 4 min read

To ensure that our app's user interface behaves correctly during various user actions, iOS provides the XCTest framework for creating UI tests.

In this guide, we'll walk through writing UI tests for a SwiftUI application, including how to query UI elements and interact with them.

Let's jump in.

Sponsorship logo
Architecture & Design Patterns for iOS
This book is a practical guide to essential architectural principles and design patterns for iOS development. It covers strategies for building maintainable apps with Swift and SwiftUI, including dependency injection, navigation, common patterns, and modularization.
LEARN MORE

Introduction to XCTest for UI Testing

XCTest enables developers to write unit tests, performance tests, and UI tests.

When writing UI tests, we simulate user behavior to verify that the app’s interface functions as expected. UI tests help confirm that specific elements are displayed correctly and respond as intended to user actions.

XCTest provides tools to query the view hierarchy and interact with UI elements programmatically, ensuring reliability in our application’s design and functionality.

Preparing for UI Testing

When creating a new SwiftUI application, we can include a UI testing target by selecting the Include Tests option during project setup. This automatically creates a UI testing target in Xcode.

Alternatively, for existing projects, we can manually add a UI testing target by selecting File > New > Target > UI Testing Bundle from Xcode’s menu.

Setting up the Test Class

To write a UI test, we use a Swift class that extends XCTestCase. Xcode creates a sample test file when a UI testing target is added. Below is an example of the generated code:

import XCTest
class ExampleAppUITests: XCTestCase {
override func setUpWithError() throws {
continueAfterFailure = false
}
override func tearDownWithError() throws {
}
func testExample() throws {
let app = XCUIApplication()
app.launch()
}
}

Xcode runs every method that starts with the word test as a separate test. We can already try out and run the testExample method which simply launches the app.

We can either run all tests by selecting Product > Test or run a specific test with the play button next to the test method name. If the test target compiles without errors and the testExample gets a green checkmark, we are ready to go.

The anatomy of a XCTestCase test class

A test class typically contains the following:

  • setUpWithError: This method is called before each test and is used to set up the initial state.
  • tearDownWithError: This method runs after each test and can be used for cleanup.

Here’s an example that configures the test environment:

override func setUpWithError() throws {
continueAfterFailure = false
let app = XCUIApplication()
app.launchArguments = ["isRunningUITests"]
app.launch()
}

Using launch arguments like "isRunningUITests", we can prepare the app for testing by clearing data, mocking responses, or bypassing login flows.

In our app code, we can access arguments with the ProcessInfo class:

if ProcessInfo.processInfo.arguments.contains("isRunningUITests") {
// Prepare application for UI tests.
}

Querying UI elements

To interact with UI elements, we use the XCUIApplication class, which provides methods to locate elements in the app’s hierarchy. Elements can be queried by their accessibility identifiers.

For example, to access a button with the identifier loginButton:

let loginButton = app.buttons["loginButton"]

The XCUIElementTypeQueryProvider provides a lot of different queries such as alerts, checkBoxes, collectionViews, datePickers, images, otherElements, scrollViews, searchFields, staticTexts, toolbarButtons etc..

SwiftUI views allow us to assign accessibility identifiers using the accessibilityIdentifier modifier. Here’s an example:

Button("Login", action: {
// Login
})
.accessibilityIdentifier("loginButton")

Simulating user actions

XCTest provides various methods to simulate user actions, such as taps, swipes, and text input. For example:

loginButton.tap()

Other common interaction methods include:

Verifying state in a UI test

To verify whether an expected element is on the screen, we can use the same macros as in unit testing such as XCTAssert and XCTAssertTrue:

XCTAssertTrue(loginButton.exists)

Here’s an example for testing a login screen:

func testLogin() throws {
let app = XCUIApplication()
app.launchArguments = ["isRunningUITests"]
app.launch()
let loginButton = app.buttons["loginButton"]
XCTAssertTrue(loginButton.waitForExistence(timeout: 2))
loginButton.tap()
let usernameField = app.textFields["usernameInputField"]
XCTAssertTrue(usernameField.waitForExistence(timeout: 2))
usernameField.tap()
usernameField.typeText("user")
let passwordField = app.secureTextFields["passwordInputField"]
XCTAssertTrue(passwordField.exists)
passwordField.tap()
passwordField.typeText("password")
let submitButton = app.buttons["submitButton"]
XCTAssertTrue(submitButton.exists)
XCTAssertTrue(submitButton.isEnabled)
submitButton.tap()
}

The waitForExistence(timeout:) method assures we don't get any test failures due to animations where views might need some time to appear on the screen.

Recording a UI test

Xcode provides the possibility to record a UI test.

For that, click inside a UI test method and select Editor > Start recording UI test. The app will start and generate UI testing code for us as we interact with the app.

The recording might be helpful in some cases and is fun to play around with, but the generated code will need readjustments and improvements in most cases, so it might be more productive to just directly writing it down.

Accessibility Inspector

A helpful tool when it comes to UI testing is the Accessibility Inspector. Open it by selecting Xcode > Open Developer Tool > Accessibility Inspector in Xcode's menu.

The Accessibility Inspector shows us different accessibility values when we select a UI element in our app. We can use it to get the accessibility identifiers for the UI tests or to determine which elements require accessibility identifiers.

Sponsorship logo
Preparing for a technical iOS job interview
Preparing for a technical iOS Job Interview with over 300 questions & answers. Covering Swift & Objective-C, SwiftUI & UIKit, Combine, HTTP Networking, iOS File System, Core Data, Concurrency with async/await, Security, Automated Testing, Dependency Management, AI & Machine Learning and more.
LEARN MORE
Sponsorship logo
Architecture & Design Patterns for iOS
This book is a practical guide to essential architectural principles and design patterns for iOS development. It covers strategies for building maintainable apps with Swift and SwiftUI, including dependency injection, navigation, common patterns, and modularization.
LEARN MORE
Sponsorship logo
Become a sponsor of tanaschita.com
By publishing an article on different iOS topics every week, tanaschita.com is constantly growing in the developer community and may provide a great audience for you as a sponsor.
CLICK TO LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

accessibility

swiftui

testing

xcode

ios

Automating accessibility audits for SwiftUI apps with XCTest

Learn how to detect common accessibility issues automatically as part of a UI test suite.

28 Sep 2026 · 5 min read

Latest articles and tips

© 2026 tanaschita.com

Privacy policy

Impressum