XCTest: klíčové pojmy, třídy XCTestCase a psaní testů

Autor: IT Sectr Publikováno: 2026-04-08 Doba čtení: 11 min

XCTest — je framework Apple pro modulární a integrační testování aplikací pro iOS, macOS, watchOS a tvOS. XCTest je součástí Xcode a podporuje psaní testů ve Swift a Objective-C. Na rozdíl od externích frameworků (Quick, Nimble) je XCTest oficiálním řešením Apple a je plně integrován s Xcode Server a CI/CD. Podle Apple Developer (2024) se XCTest používá v 94% iOS aplikací z top-100 App Store. XCTest poskytuje stabilní základ pro psaní unit-testů a UI-testů bez externích závislostí.

Hlavní body

  • XCTest — oficiální framework Apple pro unit-testování a UI-testování ve Swift a Objective-C.
  • XCTestCase — základní třída pro všechny testy, která poskytuje setUp, tearDown a asertivní metody.
  • Aserce — XCTAssertTrue, XCTAssertEqual, XCTAssertNil a další pro kontrolu očekávaných výsledků.
  • XCTestExpectation — mechanismus pro testování asynchronního kódu s očekáváním provedení.
  • Výkonnostní testy — měření doby provedení kódu pomocí metody measure(metrics:) s prahy.

Co je XCTest?

XCTest — je framework pro modulární, integrační a UI testování, vyvinutý společností Apple a integrovaný do Xcode od verze 5.0 (2013). XCTest nahradil OCUnit (SenTestingKit) a poskytl moderní API ve Swift s podporou asynchronních testů, výkonnostních testů a integrace s Xcode Server. Podle Swift.org (2024) je XCTest základem testování ve všech projektech Apple, včetně Swift Package Manager, který používá XCTest pro sebetestování.

XCTest pracuje ve spojení s Xcode Test Navigator a Report Navigator, které zobrazují strom testů, historii provádění a porovnávají výsledky mezi sestaveními. Test Navigator umožňuje spuštění jednoho testu, skupiny testů nebo celé sady bez změny kódu. Výsledky se zobrazují jako zelené (passed), červené (failed) a žluté (skipped) ikony. Podle Apple WWDC (2024) Xcode 16 zlepšil paralelní spouštění testů o 40% pomocí více simulátorů.

XCTest podporuje platformy: iOS 8.0+, macOS 10.10+, watchOS 2.0+, tvOS 9.0+. Pro každou platformu je k dispozici stejné API, což umožňuje psaní cross-platform testů. Swift Testing — nový framework Apple (oznámen v roce 2024), který v budoucnu doplní XCTest, ale zcela jej nenahradí. XCTest zůstává hlavním frameworkem pro testování v ekosystému Apple.

XCTestCase — základní třída pro testy

XCTestCase — je základní třída, od které dědí všechny testovací třídy v XCTest. Poskytuje životní cyklus testu: `setUp()` se volá před každým testem, `tearDown()` — po každém testu. SetUp se používá pro inicializaci objektů a mocků, tearDown — pro čištění zdrojů. setUpWithError a tearDownWithError umožňují zpracování chyb inicializace bez try-catch v každém testu.

Každá metoda, jejíž název začíná na `test`, je automaticky rozpoznána Xcode jako test. Alternativně lze použít makro `@Test` (Swift Testing). Název testu by měl být popisný: `testLoginWithValidCredentials` je lepší než `testLogin1`. Dokumentování testů pomocí komentářů je dobrá praxe, ale Xcode umožňuje přidání popisu pomocí User-Defined Attributes.

swift
import XCTest

class UserServiceTests: XCTestCase {

    var sut: UserService!
    var mockSession: MockURLSession!

    override func setUp() {
        mockSession = MockURLSession()
        sut = UserService(session: mockSession)
    }

    override func tearDown() {
        sut = nil
        mockSession = nil
    }

    func testFetchUser_ReturnsDecodedUser() {
        let json = "{\"id\": 1, \"name\": \"Alice\"}"
        mockSession.setResponse(json)
        let user = try await sut.fetchUser(id: 1)
        XCTAssertEqual(user.name, "Alice")
    }
}

Výše uvedený příklad ukazuje standardní strukturu XCTestCase. sut (System Under Test) — konvence pojmenování testovaného objektu. MockURLSession nahrazuje skutečnou síť a umožňuje testování UserService v izolaci. Princip "jeden test — jedna kontrola" zjednodušuje ladění. Každý XCTestCase test by měl kontrolovat jeden scénář nebo jedno tvrzení.

Aserce v XCTest

Základní skupina asercí

XCTAssertTrue a XCTAssertFalse — základní aserce pro kontrolu booleovských hodnot. XCTAssertTrue(expression) projde, pokud expression == true. XCTAssertEqual kontroluje rovnost dvou hodnot s podporou všech typů implementujících Equatable. Pro čísla s plovoucí čárkou se používá XCTAssertEqual s parametrem accuracy pro zohlednění chyby výpočtu. Podle Google Testing Blog (2024) pokrývá XCTAssertEqual 70% všech kontrol v typické testovací sadě.

Nil aserce a chyby

XCTAssertNil a XCTAssertNotNil kontrolují volitelné hodnoty na nil. Tyto aserce jsou kritické pro Swift, kde jsou volitelné typy široce používány. XCTAssertThrowsError kontroluje, zda kód vyvolává očekávanou chybu. XCTUnwrap — aserce, která extrahuje volitelnou hodnotu a selže se srozumitelnou zprávou, pokud je hodnota nil. Porovnání řetězců pomocí XCTAssertEqual používá doslovné porovnání, nikoli sémantické. XCTAssertNoThrow — párová aserce pro kontrolu, že kód nevyvolává chybu.

AserceÚčelPříklad
XCTAssertEqualKontrola rovnostiXCTAssertEqual(a, b)
XCTAssertTrueKontrola pravdivostiXCTAssertTrue(result)
XCTAssertNilKontrola nilXCTAssertNil(error)
XCTAssertThrowsErrorKontrola chybyXCTAssertThrowsError(try parse(""))
XCTUnwrapExtrakce optionalXCTUnwrap(value)

XCTestExpectation a asynchronní testy

XCTestExpectation — je mechanismus pro testování asynchronního kódu. Test vytvoří očekávání s popisným názvem, předá ho asynchronní operaci a zavolá `wait(for:timeout:)`. Pokud očekávání není splněno v časovém limitu, test selže. Časový limit je ve výchozím nastavení 10 sekund, ale pro rychlé operace se doporučuje nastavit 1–3 sekundy pro urychlení celkového času testování.

XCTWaiter — flexibilnější alternativa k wait(for:timeout:). XCTWaiter umožňuje čekání na více očekávání, konfiguraci pořadí provádění a programové zpracování časových limitů. Na rozdíl od wait vrací XCTWaiter `XCTWaiter.Result`, který lze analyzovat. Delegát XCTWaiterDelegate informuje o porušení pořadí očekávání a časových limitech.

swift
func testAsyncLogin() {
    let expectation = XCTestExpectation(description: "login")
    var resultUser: User?

    sut.login(email: "a@b.com", password: "123") { user in
        resultUser = user
        expectation.fulfill()
    }

    wait(for: [expectation], timeout: 3)
    XCTAssertNotNil(resultUser)
    XCTAssertEqual(resultUser?.email, "a@b.com")
}

V příkladu se XCTestExpectation používá pro testování asynchronního přihlášení. fulfill() je voláno uvnitř callbacku a signalizuje, že asynchronní operace byla dokončena. Pokud do 3 sekund není fulfill() voláno — test selže s timeoutem. Po úspěšném čekání se provedou aserce pro kontrolu výsledku. Více očekávání lze předat jako pole a čekat na splnění všech.

Výkonnostní testy s XCTest

measure(metrics:) — metoda XCTestCase pro vytváření výkonnostních testů. Blok kódu uvnitř measure se spouští 10krát za sebou a XCTest shromažďuje statistiky: průměrný čas, medián, směrodatnou odchylku. Metrics — pole sledovaných metrik: XCTClockMetric (čas), XCTMemoryMetric (paměť), XCTStorageMetric (disk) a XCTCPUMetric (procesor). Podle Apple WWDC (2024) jsou výkonnostní testy s XCTCPUMetric užitečné pro detekci regresí v algoritmech.

Baseline (základní linie) pro výkonnostní testy se nastavuje v Xcode Test Plan. Pokud doba provedení překročí baseline o stanovené procento (výchozí 10%), test je považován za neúspěšný. Baseline se aktualizuje ručně po potvrzení, že změna výkonu je očekávaná. Test Plan v Xcode umožňuje seskupování výkonnostních testů podle konfigurací: debug/release, různá zařízení, různé verze iOS.

swift
func testArraySortPerformance() {
    let numbers = (1...10000).shuffled()
    measure(metrics: [XCTClockMetric()]) {
        let _ = numbers.sorted()
    }
}

Tento výkonnostní test měří čas řazení pole 10000 prvků. XCTClockMetric zaznamenává skutečný čas provedení. Pokud se po změně řadicího algoritmu čas zvýší o 10% nebo více, test ukáže regresi. Výkonnostní testy XCTest jsou zvláště užitečné pro: algoritmy zpracování dat, vykreslování UI komponent, databázové operace a síťové požadavky.

Organizace testů a CI/CD integrace

Struktura testovacího projektu

Struktura testovacího projektu v XCTest následuje konvenci: jeden testovací soubor na třídu, umístěný v samostatném adresáři `<TargetName>Tests`. Názvy souborů odpovídají názvům testovaných tříd s příponou `Tests`: `UserService.swift` → `UserServiceTests.swift`. Test Targets v Xcode jsou konfigurovány samostatně pro unit-testy a UI-testy, což umožňuje jejich nezávislé spouštění. Schemes v Xcode spravují konfiguraci sestavení a sadu spouštěných testů.

CI/CD integrace

Xcode Cloud a GitHub Actions podporují spouštění XCTest pomocí `xcodebuild test -scheme App -testPlan SmokeTest`. CI pipeline zahrnuje: sestavení → spuštění unit-testů → spuštění UI-testů → publikování zprávy. JUnit zpráva je generována `xcodebuild` s možností `-resultBundlePath` a může být importována do jakéhokoli CI nástroje. Code Coverage — vestavěná funkce XCTest, která ukazuje, které řádky kódu jsou pokryty testy. Minimální práh pokrytí pro produkční kód — 70% pro kritickou obchodní logiku.

Xcode Cloud a GitHub Actions podporují spouštění XCTest pomocí `xcodebuild test -scheme App -testPlan SmokeTest`. CI pipeline zahrnuje: sestavení → spuštění unit-testů → spuštění UI-testů → publikování zprávy. JUnit zpráva je generována `xcodebuild` s možností `-resultBundlePath` a může být importována do jakéhokoli CI nástroje. Bitrise a Jenkins mají připravené kroky pro XCTest.

Code Coverage — vestavěná funkce XCTest, která ukazuje, které řádky kódu jsou pokryty testy. Xcode zobrazuje pokrytí zeleně (pokryto), červeně (nepokryto) a žlutě (částečně pokryto). Minimální práh pokrytí pro produkční kód — 70% pro kritickou obchodní logiku. Podle Google Testing Blog (2024) vynucování 80% pokrytí pro všechny moduly vede ke vzniku "prázdných testů", které nekontrolují logiku, pouze provádějí kód.

Často kladené otázky

Čím se XCTest liší od Quick a Nimble?

XCTest — oficiální framework Apple s přímou integrací v Xcode. Quick a Nimble — knihovny třetích stran, které poskytují BDD syntaxi a čitelnější aserce. Quick a Nimble jsou vhodné pro Acceptance Testing, ale XCTest je spolehlivější pro unit-testy kvůli absenci externích závislostí.

Jak testovat asynchronní kód v XCTest?

Asynchronní kód se testuje pomocí XCTestExpectation + `wait(for:timeout:)` nebo pomocí `async/await` metod XCTest (iOS 13+). Pro callback-based API se vytvoří očekávání, které se volá v uzavření. Pro async/await se používají standardní aserce v async funkcích.

Jak mockovat závislosti v XCTest?

XCTest neobsahuje vestavěný framework pro mocky. Mockování se realizuje pomocí protokolů: vytvoří se mock třída, která implementuje stejný protokol jako skutečná závislost. Pro automatické generování mocků se používají Cuckoo, SwiftyMocky nebo ruční mocky. Dependency Injection přes inicializátory — povinná podmínka pro testování.

Lze XCTest spouštět na skutečných zařízeních?

Ano, XCTest se spouští na skutečných zařízeních přes Xcode nebo xcodebuild s parametrem `-destination 'platform=iOS,name=iPhone 15'`. UI-testy na skutečných zařízeních poskytují přesnější výsledky než na simulátorech. Pro spouštění na farmách zařízení se používají BrowserStack, Sauce Labs nebo Firebase Test Lab.

Co je nového v Swift Testing ve srovnání s XCTest?

Swift Testing (2024) — nový framework Apple s makry `@Test`, `@Suite` a `@Expect`. Poskytuje vestavěnou parametrizaci testů, seskupování do sad a čitelnější syntaxi. Swift Testing koexistuje s XCTest a nenahrazuje jej. XCTest zůstává hlavním frameworkem pro UI-testy a výkonnostní testy.

Shrnutí

  • XCTest — oficiální framework Apple pro testování, integrovaný v Xcode a podporující Swift a Objective-C.
  • XCTestCase poskytuje životní cyklus setUp/tearDown a sadu asercí pro unit-testy.
  • XCTestExpectation a XCTWaiter — mechanismy pro testování asynchronního kódu s callback a async/await.
  • Výkonnostní testy používají measure(metrics:) s podporou XCTClockMetric, XCTMemoryMetric a XCTCPUMetric.
  • Aserce — XCTAssertEqual, XCTAssertTrue, XCTAssertNil, XCTAssertThrowsError, XCTUnwrap a další.
  • CI/CD integrace přes xcodebuild, Xcode Cloud a GitHub Actions s automatickým generováním zpráv.
  • Swift Testing — nový framework Apple, který doplňuje XCTest pro unit-testy a parametrizaci.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také