Developing UI tests for an iOS application (XCUITest)

TRUETECH is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Developing UI tests for an iOS application (XCUITest)
Medium
~3-5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

UI Test Development for iOS Application (XCUITest)

XCUITest is instrumental testing: test runs on real simulator or device, controls app via Accessibility API, taps buttons and checks correct text appears on screen. Much slower than unit tests, but covers what unit tests can't — navigation, data display, input reaction.

Main Patterns and Common Errors

Most common XCUITest problem — fragility. Test searches element by label, designer changes button text — test fails. Correct solution: accessibilityIdentifier.

// In app code
button.accessibilityIdentifier = "loginButton"

// In test
let loginButton = app.buttons["loginButton"]
XCTAssertTrue(loginButton.exists)
loginButton.tap()

accessibilityIdentifier not displayed to user and doesn't change on localization. Only reliable way to address elements.

Second antipattern: sleep(3) instead of element wait. Test with hardcoded pauses unstable and slow.

// Bad
sleep(3)
XCTAssertTrue(app.staticTexts["Welcome"].exists)

// Correct
let welcomeText = app.staticTexts["Welcome"]
XCTAssertTrue(welcomeText.waitForExistence(timeout: 5))

waitForExistence(timeout:) blocks thread until element appears or timeout expires. Test finishes faster on success and doesn't depend on CI machine speed.

Page Object Pattern

With 20+ test scenarios duplication becomes problem. Page Object isolates UI interactions:

struct LoginScreen {
    private let app: XCUIApplication

    var emailField: XCUIElement { app.textFields["emailInput"] }
    var passwordField: XCUIElement { app.secureTextFields["passwordInput"] }
    var loginButton: XCUIElement { app.buttons["loginButton"] }
    var errorLabel: XCUIElement { app.staticTexts["errorMessage"] }

    func login(email: String, password: String) {
        emailField.tap()
        emailField.typeText(email)
        passwordField.tap()
        passwordField.typeText(password)
        loginButton.tap()
    }
}

// Test reads as scenario, not as set of UI instructions
func testLoginWithInvalidCredentials() {
    let loginScreen = LoginScreen(app: app)
    loginScreen.login(email: "[email protected]", password: "badpass")
    XCTAssertTrue(loginScreen.errorLabel.waitForExistence(timeout: 3))
}

Backend Mocking

UI tests shouldn't depend on real server. Two approaches:

Launch arguments — app in test mode loads mock data:

// setUp
app.launchArguments = ["--uitesting", "--mock-auth-success"]
// In AppDelegate / SceneDelegate
if ProcessInfo.processInfo.arguments.contains("--uitesting") {
    setupMockDependencies()
}

Local HTTP mockSwifter or GCDWebServer runs local server in test host. More realistic, but more complex setup.

Screenshot Tests

XCTAttachment saves screenshots at test moment for later analysis. For UI snapshot testing (detect visual regressions) use SnapshotTesting from Point-Free — compares PNG snapshots with baselines.

CI Execution

- name: Run UI Tests
  run: |
    xcodebuild test \
      -scheme MyApp \
      -destination 'platform=iOS Simulator,name=iPhone 15 Pro,OS=17.2' \
      -resultBundlePath TestResults.xcresult \
      -testPlan UITests

Parallel execution via -parallel-testing-enabled YES speeds up large suite. On Firebase Test Lab — matrix of physical devices for final run before release.

What We Cover

  • Critical user flows: registration, login, onboarding, payment
  • Navigation edge cases: deep link, push notification tap, force close and return
  • Accessibility: VoiceOver via XCUIApplication().activate() in accessibility mode

Timeframe: 3–5 days for creating basic suite for critical flows with Page Object structure and CI integration.