XCUITest: co to jest, zasady działania i testowanie UI iOS

Autor: IT Sectr Opublikowano: 2026-04-09 Czas czytania: 8 min

XCUITest — to framework Apple do testowania UI aplikacji iOS, iPadOS i macOS, wbudowany bezpośrednio w XCTest i Xcode. Umożliwia symulację działań użytkownika: kliknięcia, wprowadzanie tekstu, przesunięcia, przewijanie i gesty — z dostępem do wewnętrznego stanu elementów interfejsu. Według Apple Developer Documentation, 2025, XCUIApplication jest punktem wejścia dla wszystkich testów UI i zapewnia dostęp do hierarchii elementów ekranu.

Najważniejsze

  • XCUITest — natywny framework Apple do testowania UI, wbudowany w Xcode
  • Podejście white-box zapewnia dostęp do atrybutów Accessibility i hierarchii elementów
  • Testy pisze się w Swift lub Objective-C w integracji z XCTest
  • Nagrywanie testów dostępne przez wbudowany rejestrator w Xcode
  • Uruchamianie odbywa się na symulatorze iOS lub rzeczywistym urządzeniu bez dodatkowych serwerów

Czym jest XCUITest

XCUITest — to framework do testowania UI, wydany przez Apple w Xcode 7 (2015 rok). Zastąpił UI Automation (UIA) i stał się standardowym narzędziem do zautomatyzowanego testowania interfejsu na platformach Apple. XCUITest jest w pełni zintegrowany z XCTest — jednolitym frameworkiem testowym Apple.

Różnica w stosunku do testów jednostkowych XCTest

W przeciwieństwie do testów jednostkowych, które sprawdzają logikę na poziomie klas i metod, XCUITest testuje interfejs użytkownika poprzez symulację działań. Testy uruchamiane są w osobnym procesie od aplikacji i komunikują się z nią przez Accessibility API — zapewnia to izolację i niezawodność.

Zalety natywnego podejścia

XCUITest nie wymaga instalowania zewnętrznych serwerów (w przeciwieństwie do Appium) ani dodatkowych bibliotek do komunikacji z urządzeniem. Wszystko, co potrzebne, jest już zawarte w Xcode. Zapewnia to najlepszą kompatybilność z nowymi wersjami iOS i natychmiastowy dostęp do nowych gestów i elementów sterowania.

Architektura XCUITest i XCTest

Architektura XCUITest opiera się na dwóch kluczowych klasach: XCUIApplication — uruchomiona testowana aplikacja, oraz XCUIElement — element interfejsu. Test-runner XCTest zarządza cyklem życia testów: setUp, metody testowe, tearDown. XCUITest uruchamiany jest jako osobny proces, który steruje aplikacją przez most Accessibility.

Hierarchia elementów

Każdy element UI jest reprezentowany przez obiekt XCUIElement, który zawiera metody do odpytywania stanu (exists, isHittable, label, value) i akcji (tap, pressForDuration, swipeUp, typeText). Elementy są zorganizowane w hierarchię poprzez łańcuchy zapytań: app.buttons[].staticTexts[].tables[]. Umożliwia to elastyczne znajdowanie dowolnego elementu na ekranie.

Accessibility i lokalizatory

XCUITest używa atrybutów Accessibility do identyfikacji elementów: accessibilityIdentifier — identyfikator programowy, oraz accessibilityLabel — opis dla VoiceOver. Zaleca się ustawianie accessibilityIdentifier w kodzie aplikacji — czyni to testy stabilnymi niezależnie od lokalizacji i układu.

Pisanie testów UI w XCUITest

Testy XCUITest pisze się w Swift z użyciem składni XCTest. Każda klasa testowa dziedziczy po XCTestCase i zawiera metody zaczynające się od test. W metodzie setUp uruchamiana jest aplikacja z odpowiednią konfiguracją, a w tearDown następuje czyszczenie i zakończenie sesji.

Podstawowy scenariusz testowy

Typowy test: znajdź element → wykonaj akcję → sprawdź wynik. Wyszukiwanie elementu odbywa się przez zapytania podrzędne XCUIElementQuery: app.buttons["loginButton"], app.textFields["email"]. Akcje: .tap(), .typeText("text"), .swipeUp(). Sprawdzenia: XCTAssertTrue(element.exists) lub XCTAssertEqual(element.label, "expected").

swift
import XCTest

class LoginTests: XCTestCase {
    let app = XCUIApplication()

    override func setUp() {
        continueAfterFailure = false
        app.launch()
    }

    func testLoginWithValidCredentials() {
        let emailField = app.textFields["emailInput"]
        emailField.tap()
        emailField.typeText("user@test.com")

        let passwordField = app.secureTextFields["passwordInput"]
        passwordField.tap()
        passwordField.typeText("password123")

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

        let homeLabel = app.staticTexts["homeTitle"]
        XCTAssertTrue(homeLabel.exists)
    }
}

Oczekiwania i synchronizacja

XCUITest obsługuje jawne oczekiwania przez XCTWaiter i predykaty NSPredicate. Na przykład oczekiwanie na pojawienie się elementu w ciągu 5 sekund: XCTWaiter().wait(for: [expectation], timeout: 5). W przeciwieństwie do Detox, XCUITest nie ma automatycznej synchronizacji z żądaniami sieciowymi.

swift
// Oczekiwanie na pojawienie się elementu z limitem czasu
let expectedElement = app.staticTexts["welcomeMessage"]
let existsPredicate = NSPredicate(format: "exists == true")
let expectation = XCTNSNotificationExpectation(object: expectedElement)
let result = XCTWaiter().wait(
    for: [expectation], timeout: 5
)
XCTAssertEqual(result, .completed)

Zaawansowane możliwości XCUITest

XCUITest obsługuje testowanie złożonych scenariuszy: gesty multitouch, powiadomienia push, Deep Links, SFSafariViewController i interakcje między aplikacjami. Intencje Siri mogą być również testowane przez XCUITest z użyciem symulacji Siri Remote.

Testowanie gestów

XCUITest obsługuje wszystkie popularne gesty: tap, doubleTap, pressForDuration, swipeUp/Down/Left/Right, pinch, rotate, twoFingerTap. Do złożonych scenariuszy używa się XCUIGesture z dowolnymi współrzędnymi i czasem trwania. Pozwala to testować niestandardowe gesty, takie jak rysowanie lub drag-and-drop.

Przechwytywanie żądań sieciowych

Od Xcode 12, XCUITest obsługuje przechwytywanie żądań sieciowych przez XCTestExpectation i URLProtocol. Umożliwia to testowanie aplikacji w trybie offline lub z podmienionymi odpowiedziami serwera bez modyfikacji kodu aplikacji.

XCUITest w CI/CD

XCUITest uruchamiany jest w środowiskach CI przez xcodebuild z flagą test. Do równoległego uruchamiania na wielu symulatorach używa się xcodebuild -testPlan z konfiguracją równoległego wykonywania w schemacie Xcode. GitHub Actions, Bitrise i Jenkins mają wbudowaną obsługę XCUITest.

Konfiguracja dla CI

Dla CI wymagane jest skonfigurowanie code signing, provisioning profiles i wskazanie destynacji (symulator lub urządzenie). Testy iOS na symulatorze nie wymagają certyfikatów. Dla rzeczywistych urządzeń potrzebny jest automatyczny podpis przez Xcode Cloud lub Fastlane.

bash
# Uruchamianie XCUITest na symulatorze przez xcodebuild
xcodebuild test \
  -project MyApp.xcodeproj \
  -scheme MyApp \
  -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.5' \
  -resultBundlePath ./TestResults \
  -parallel-testing-enabled YES \
  -parallel-testing-worker-count 4

Testowanie Accessibility przez XCUITest

XCUITest jest ściśle powiązany z Accessibility API Apple, ponieważ wyszukiwanie elementów opiera się na atrybutach dostępności. Testowanie dostępności — to nie tylko sposób znajdowania elementów, ale także sprawdzanie dostępności aplikacji dla osób z niepełnosprawnościami. XCUITest może sprawdzać accessibilityLabel, traits i hints.

Sprawdzanie VoiceOver

VoiceOver — ekranowy czytnik Apple dla niewidomych użytkowników. XCUITest pozwala sprawdzić: accessibilityLabel — czy element jest opisany zrozumiałym tekstem, accessibilityTraits — czy typ elementu odpowiada (przycisk, nagłówek, obraz), oraz accessibilityHint — czy daje podpowiedź o wyniku akcji. Te sprawdzenia są obowiązkowe do publikacji w App Store, a XCUITest automatyzuje je w ramach przebiegu regresyjnego.

Automatyczne sprawdzanie Accessibility

Od Xcode 15, XCUITest obsługuje wbudowane sprawdzanie Accessibility przez XCTAttachment z typem accessibilityAudit. Test automatycznie informuje o elementach z niewystarczającym kontrastem, niepodpisanych obrazach i nieprawidłowych traits. Zastępuje to ręczny Accessibility Inspector.

swift
// Audyt dostępności w XCUITest
func testAccessibilityAudit() {
    let app = XCUIApplication()
    app.launch()

    let audit = XCTAttachment(accessibilityAudit: app)
    add(audit)

    // Sprawdzanie konkretnego elementu
    let button = app.buttons["submitButton"]
    XCTAssertTrue(button.label.count > 0)
    XCTAssertTrue(button.isAccessibilityElement)
}

Testy wydajnościowe w XCUITest

XCUITest obsługuje pomiar wydajności UI przez XCTOSSignpostMetric i XCUIApplication.metrics. Można zmierzyć czas uruchomienia aplikacji (launch time), szybkość nawigacji, czas odpowiedzi na gesty. Testy wydajnościowe uruchamiane są z pomiarem baseline i automatycznie padają po przekroczeniu progu. Pozwala to zapobiegać regresjom wydajności, zanim trafią do użytkowników w wersji release.

Konfiguracja baseline

Baseline — to referencyjny czas wykonania testu. Xcode zapamiętuje baseline dla każdego testu na konkretnym modelu urządzenia i wersji iOS. Jeśli nowe uruchomienie przekroczy baseline o zadany procent (domyślnie 10%), test uznawany jest za niezaliczony. Do aktualizacji baseline używa się polecenia Edit Baseline w raporcie testów. Ważne jest przeliczanie baseline przy aktualizacji wersji iOS lub zmianie modelu urządzenia dla farmy CI.

Monitorowanie stabilności testów

Do śledzenia stabilności testów XCUITest używa się flag: continueAfterFailure (czy kontynuować test po pierwszym niepowodzeniu) oraz planów testowych Xcode z konfiguracjami powtórzeń. Zaleca się skonfigurowanie automatycznego ponownego uruchamiania nieudanych testów (retry) — do 3 prób dla flakujących testów związanych z timingami animacji lub opóźnieniami sieciowymi.

Testowanie powiadomień push i Deep Links

XCUITest obsługuje testowanie powiadomień push i Deep Links przez springboard i launchArguments. Dla powiadomień push używa się XCUIApplication().launchArguments z parametrem -UNUserNotificationCenter i wysyłką przez XCTest. Deep Links testuje się przez open URL z określeniem niestandardowego schematu — XCUITest przechwytuje systemowy dialog i sprawdza, czy aplikacja otworzyła się na prawidłowym ekranie. Do testowania scenariusza odpowiedzi na powiadomienie używa się XCUIApplication().springboard, który symuluje kliknięcie na baner powiadomienia w centrum powiadomień iOS. Te scenariusze są krytyczne dla aplikacji z deep linkami i kampaniami push, gdzie wymagane jest sprawdzenie poprawności obsługi wywołań zewnętrznych.

Integracja z Instruments

Do szczegółowego profilowania wydajności XCUITest integruje się z Instruments. Podczas testu można uruchomić profilowanie Time Profiler, Core Animation lub Leaks przez XCTMetric. Wyniki profilowania zapisywane są w raporcie i dostępne do analizy w Xcode. Jest to szczególnie przydatne przy optymalizacji czasu uruchomienia aplikacji, nawigacji między ekranami i wydajności animacji — typowych wąskich gardeł w aplikacjach iOS.

Często zadawane pytania

Jaka jest różnica między XCUITest a XCTest?

XCTest — to ogólny framework dla wszystkich typów testów Apple, w tym testów jednostkowych i wydajnościowych. XCUITest — to nakładka na XCTest do testowania UI, która dodaje klasy XCUIApplication, XCUIElement i XCUIElementQuery do interakcji z interfejsem.

Czy można używać XCUITest z Objective-C?

Tak, XCUITest obsługuje zarówno Swift, jak i Objective-C. Jednak większość przykładów i dokumentacji Apple pisana jest w Swift. Projekty w Objective-C mogą używać XCUITest bez dodatkowej konfiguracji — framework jest dostępny przez @import XCTest.

Jak XCUITest znajduje elementy na ekranie?

XCUITest używa Accessibility API Apple. Elementy są znajdowane po accessibilityIdentifier, accessibilityLabel, typie (button, textField, staticText) lub pozycji w hierarchii. Im dokładniej określone są atrybuty Accessibility w kodzie aplikacji, tym stabilniejsze są testy.

Czy XCUITest obsługuje nagrywanie testów?

Tak, Xcode zawiera wbudowany rejestrator testów UI. Podczas uruchamiania testu w trybie nagrywania Xcode rejestruje wszystkie interakcje z interfejsem i generuje kod Swift. Nagrany kod można dopracować: dodać sprawdzenia, wydzielić do Page Objects i sparametryzować.

Jak uruchomić XCUITest na rzeczywistym urządzeniu?

Do uruchomienia na rzeczywistym urządzeniu należy: podłączyć urządzenie do Maca, dodać je do Apple Developer Program, skonfigurować provisioning profile, podpisać aplikację certyfikatem developerskim i wybrać urządzenie jako destynację w xcodebuild.

Podsumowanie

  • XCUITest — natywny framework Apple do testowania UI aplikacji iOS, iPadOS i macOS
  • Integracja z Xcode zapewnia nagrywanie testów, równoległe uruchamianie i wbudowane raporty
  • XCUIApplication i XCUIElement — kluczowe klasy do interakcji z aplikacją
  • Atrybuty Accessibility używane są jako niezawodne lokalizatory, stabilne przy zmianach układu
  • Oczekiwania realizowane są przez XCTWaiter i NSPredicate — automatycznej synchronizacji brak
  • CI/CD obsługiwane przez xcodebuild z równoległym uruchamianiem na symulatorach
  • Zaawansowane scenariusze obejmują multitouch, Siri Intents, przechwytywanie żądań sieciowych i Deep Links

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również