Skip to content

UI Testing With XCTest (SwiftUI)

A SwiftUI guide for coding agents. Also covers xcuiapplication, ui test login flow, accessibility identifier testing, waitforexistence, launch arguments test setup, disable animations tests.

XCTest drives the app through the Accessibility APIs, so UI tests work against SwiftUI and UIKit alike, and against a coupled codebase no unit test can reach. A UI test scripts one user flow and asserts what the screen shows.

Test Case Shape

Create the target with File > New > Target > UI Testing Bundle. Every method starting with test runs as a test; setUp runs before each one and relaunches the app so runs stay consistent.

final class UITests: XCTestCase {
  var app: XCUIApplication!

  override func setUp() {
    continueAfterFailure = false
    app = XCUIApplication()
    app.launchArguments = ["testing"]
    app.launch()
  }

  func testWelcomeMessage() {
    XCTAssertTrue(app.staticTexts["Hello World!"].exists)
  }
}

Finding and Driving Views

Query by element type and subscript; the string matches the accessibility label or identifier. Buttons, labels, and switches use their titles automatically; lists and collections need an explicit identifier.

let email = app.textFields["email"]
email.tap()
email.typeText("[email protected]")

app.switches["rememberMe"].tap()
app.buttons["login"].tap()

// SwiftUI side:
List { Text("news item") }
  .accessibilityIdentifier("newsList")
SecureField("password", text: $viewModel.password)
  .accessibilityLabel("password")

Assert on async outcomes with waitForExistence(timeout:), which returns true as soon as the element appears and false when the timeout passes. Plain .exists checks only the current instant.

XCTAssertTrue(app.staticTexts["Hello World!"].waitForExistence(timeout: 5))

Speed and Isolation

UI tests boot the whole app, so keep them for the crucial flows and let unit tests carry the volume. Use the launch argument to detect a test run, then reset state (user defaults, keychain, local database) and disable animations.

func applicationDidFinishLaunching(_ application: UIApplication) {
  if CommandLine.arguments.contains("testing") {
    UIView.setAnimationsEnabled(false)
  }
}

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-ui-testing-in-swift-with-xctest-framework" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems