XCTest: kulcsfogalmak, XCTestCase osztályok és tesztek írása

Szerző: IT Sectr Megjelenés: 2026-04-08 Olvasási idő: 11 perc

Az XCTest — az Apple keretrendszere az iOS, macOS, watchOS és tvOS alkalmazások moduláris és integrációs teszteléséhez. Az XCTest az Xcode része, és támogatja a tesztek írását Swift és Objective-C nyelven. A külső keretrendszerekkel (Quick, Nimble) ellentétben az XCTest az Apple hivatalos megoldása, és teljes mértékben integrált az Xcode Serverrel és a CI/CD-vel. Az Apple Developer (2024) szerint az XCTest az App Store top-100 iOS alkalmazásának 94%-ában használatos. XCTest stabil alapot biztosít az unit-tesztek és UI-tesztek írásához külső függőségek nélkül.

Főbb pontok

  • XCTest — az Apple hivatalos keretrendszere unit-teszteléshez és UI-teszteléshez Swift és Objective-C nyelven.
  • XCTestCase — az alaposztály minden teszthez, amely setUp, tearDown és asszertációs metódusokat biztosít.
  • Asszertációk — XCTAssertTrue, XCTAssertEqual, XCTAssertNil és mások a várt eredmények ellenőrzéséhez.
  • XCTestExpectation — mechanizmus aszinkron kód teszteléséhez végrehajtási várakozással.
  • Teljesítménytesztek — a kód végrehajtási idejének mérése a measure(metrics:) metódussal küszöbértékekkel.

Mi az XCTest?

XCTest — egy keretrendszer moduláris, integrációs és UI teszteléshez, amelyet az Apple fejlesztett ki és az Xcode-ba épített az 5.0 verziótól (2013) kezdve. Az XCTest felváltotta az OCUnit-ot (SenTestingKit), és modern API-t biztosított Swift-ben aszinkron tesztek, teljesítménytesztek és Xcode Server integráció támogatásával. A Swift.org (2024) szerint az XCTest a tesztelés alapja minden Apple projektben, beleértve a Swift Package Managert is, amely az XCTest-et használja önellenőrzésre.

Az XCTest az Xcode Test Navigator és Report Navigator segítségével működik, amelyek megjelenítik a tesztfát, a végrehajtási előzményeket és összehasonlítják az eredményeket a build-ek között. Test Navigator lehetővé teszi egyetlen teszt, tesztcsoport vagy a teljes készlet futtatását a kód módosítása nélkül. Az eredmények zöld (passed), piros (failed) és sárga (skipped) ikonként jelennek meg. Az Apple WWDC (2024) szerint az Xcode 16 40%-kal javította a párhuzamos tesztfuttatást több szimulátor használatával.

Az XCTest a következő platformokat támogatja: iOS 8.0+, macOS 10.10+, watchOS 2.0+, tvOS 9.0+. Minden platformhoz ugyanaz az API érhető el, ami lehetővé teszi a cross-platform tesztek írását. Swift Testing — egy új Apple keretrendszer (2024-ben bejelentve), amely a jövőben kiegészíti az XCTest-et, de nem váltja fel teljesen. Az XCTest továbbra is a fő tesztelési keretrendszer marad az Apple ökoszisztémában.

XCTestCase — az alaposztály a tesztekhez

XCTestCase — az alaposztály, amelyből az összes tesztosztály származik az XCTest-ben. Biztosítja a teszt életciklusát: a `setUp()` minden teszt előtt, a `tearDown()` minden teszt után hívódik meg. A setUp az objektumok és mock-ok inicializálására, a tearDown az erőforrások tisztítására szolgál. setUpWithError és tearDownWithError lehetővé teszik az inicializálási hibák kezelését try-catch nélkül minden tesztben.

Minden metódus, amelynek neve `test`-tel kezdődik, automatikusan tesztként kerül felismerésre az Xcode-ban. Alternatívaként a `@Test` makró (Swift Testing) is használható. A teszt nevének leírónak kell lennie: `testLoginWithValidCredentials` jobb, mint `testLogin1`. Dokumentálás a tesztek kommentekkel történő ellátása jó gyakorlat, de az Xcode lehetővé teszi a leírás hozzáadását User-Defined Attributes segítségével.

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")
    }
}

A fenti példa az XCTestCase szabványos szerkezetét mutatja be. sut (System Under Test) — a tesztelt objektum elnevezési konvenciója. A MockURLSession helyettesíti a valós hálózatot, lehetővé téve a UserService elkülönített tesztelését. Az "egy teszt — egy ellenőrzés" elv leegyszerűsíti a hibakeresést. Minden XCTestCase tesztnek egy forgatókönyvet vagy egy állítást kell ellenőriznie.

Asszertációk az XCTest-ben

Az asszertációk alapcsoportja

XCTAssertTrue és XCTAssertFalse — alap asszertációk logikai értékek ellenőrzésére. Az XCTAssertTrue(expression) akkor megy át, ha expression == true. Az XCTAssertEqual két érték egyenlőségét ellenőrzi, támogatva minden típust, amely implementálja az Equatable-t. Lebegőpontos számokhoz az XCTAssertEqual accuracy paraméterrel használatos a számítási hiba figyelembevételére. A Google Testing Blog (2024) szerint az XCTAssertEqual a tipikus teszthalmaz összes ellenőrzésének 70%-át fedi le.

Nil asszertációk és hibák

XCTAssertNil és XCTAssertNotNil az opcionális értékeket nil-ra ellenőrzi. Ezek az asszertációk kritikusak a Swift számára, ahol az opcionális típusok széles körben használatosak. Az XCTAssertThrowsError ellenőrzi, hogy a kód dob-e várt hibát. XCTUnwrap — asszertáció, amely kicsomagolja az opcionális értéket, és érthető üzenettel megbukik, ha az érték nil. A stringek összehasonlítása az XCTAssertEqual-lel literális összehasonlítást használ, nem szemantikusat. XCTAssertNoThrow — pár asszertáció annak ellenőrzésére, hogy a kód nem dob hibát.

AsszertációCélPélda
XCTAssertEqualEgyenlőség ellenőrzéseXCTAssertEqual(a, b)
XCTAssertTrueIgazság ellenőrzéseXCTAssertTrue(result)
XCTAssertNilNil ellenőrzéseXCTAssertNil(error)
XCTAssertThrowsErrorHiba ellenőrzéseXCTAssertThrowsError(try parse(""))
XCTUnwrapOptional kicsomagolásaXCTUnwrap(value)

XCTestExpectation és aszinkron tesztek

XCTestExpectation — mechanizmus az aszinkron kód tesztelésére. A teszt létrehoz egy várakozást leíró névvel, átadja az aszinkron műveletnek és meghívja a `wait(for:timeout:)`-t. Ha a várakozás nem teljesül a timeout alatt, a teszt megbukik. Időtúllépés alapértelmezés szerint 10 másodperc, de gyors műveletekhez 1–3 másodperc beállítása javasolt a teljes tesztidő felgyorsításához.

XCTWaiter — rugalmasabb alternatíva a wait(for:timeout:)-hoz. Az XCTWaiter lehetővé teszi több várakozásra való várakozást, a végrehajtási sorrend beállítását és a timeout-ok programozott kezelését. A wait-tel ellentétben az XCTWaiter `XCTWaiter.Result`-ot ad vissza, amely elemezhető. Delegált XCTWaiterDelegate értesít a várakozási sorrend megsértéséről és a timeout-okról.

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")
}

A példában az XCTestExpectation az aszinkron bejelentkezés tesztelésére szolgál. fulfill() a callback-en belül hívódik meg, jelezve, hogy az aszinkron művelet befejeződött. Ha 3 másodpercen belül a fulfill() nem hívódik meg — a teszt timeout-tal megbukik. A sikeres várakozás után az asszertációk végrehajtódnak az eredmény ellenőrzésére. Több várakozás tömbként adható át, és várható az összes teljesülése.

Teljesítménytesztek az XCTest-tel

measure(metrics:) — az XCTestCase metódusa teljesítménytesztek létrehozásához. A measure-en belüli kódblokk 10-szer egymás után fut le, és az XCTest statisztikákat gyűjt: átlagos idő, medián, szórás. Metrics — a követett metrikák tömbje: XCTClockMetric (idő), XCTMemoryMetric (memória), XCTStorageMetric (lemez) és XCTCPUMetric (processzor). Az Apple WWDC (2024) szerint az XCTCPUMetric-tel végzett teljesítménytesztek hasznosak az algoritmusok regresszióinak felderítésére.

Baseline (alapvonal) a teljesítménytesztekhez az Xcode Test Plan-ben kerül beállításra. Ha a végrehajtási idő meghatározott százalékkal (alapértelmezett 10%) meghaladja a baseline-t, a teszt sikertelennek minősül. A baseline manuálisan frissítésre kerül, miután megerősítést nyert, hogy a teljesítményváltozás várható. Test Plan az Xcode-ban lehetővé teszi a teljesítménytesztek konfigurációk szerinti csoportosítását: debug/release, különböző eszközök, különböző iOS verziók.

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

Ez a teljesítményteszt egy 10000 elemből álló tömb rendezési idejét méri. XCTClockMetric rögzíti a tényleges végrehajtási időt. Ha a rendezési algoritmus megváltoztatása után az idő 10%-kal vagy többel nő, a teszt regressziót jelez. Az XCTest teljesítménytesztek különösen hasznosak: adatfeldolgozó algoritmusokhoz, UI komponensek rendereléséhez, adatbázis-műveletekhez és hálózati kérésekhez.

Tesztek szervezése és CI/CD integráció

A tesztprojekt szerkezete

A tesztprojekt szerkezete az XCTest-ben a következő konvenciót követi: egy tesztfájl osztályonként, külön `<TargetName>Tests` könyvtárba helyezve. A fájlnevek megfelelnek a tesztelt osztályok nevének `Tests` utótaggal: `UserService.swift` → `UserServiceTests.swift`. A Test Targets az Xcode-ban külön vannak konfigurálva az unit-tesztekhez és UI-tesztekhez, lehetővé téve független futtatásukat. Schemes az Xcode-ban a build konfigurációt és a futtatott tesztek halmazát kezelik.

CI/CD integráció

Xcode Cloud és GitHub Actions támogatják az XCTest futtatását `xcodebuild test -scheme App -testPlan SmokeTest` segítségével. A CI pipeline a következőket foglalja magában: build → unit-tesztek futtatása → UI-tesztek futtatása → jelentés közzététele. A JUnit jelentést az `xcodebuild` generálja a `-resultBundlePath` opcióval, és bármely CI eszközbe importálható. Code Coverage — az XCTest beépített funkciója, amely megmutatja, hogy a kód mely sorait fedik le a tesztek. A termelési kód minimális lefedettségi küszöbértéke — 70% a kritikus üzleti logikához.

Xcode Cloud és GitHub Actions támogatják az XCTest futtatását `xcodebuild test -scheme App -testPlan SmokeTest` segítségével. A CI pipeline a következőket foglalja magában: build → unit-tesztek futtatása → UI-tesztek futtatása → jelentés közzététele. JUnit jelentés az `xcodebuild` által generált a `-resultBundlePath` opcióval, és bármely CI eszközbe importálható. A Bitrise és a Jenkins kész lépésekkel rendelkezik az XCTest számára.

Code Coverage — az XCTest beépített funkciója, amely megmutatja, hogy a kód mely sorait fedik le a tesztek. Az Xcode a lefedettséget zölddel (lefedett), pirossal (nem lefedett) és sárgával (részben lefedett) jeleníti meg. Minimális küszöb a termelési kódhoz — 70% a kritikus üzleti logikához. A Google Testing Blog (2024) szerint a 80%-os lefedettség kötelező előírása az összes modulra "üres tesztek" megjelenéséhez vezet, amelyek nem ellenőrzik a logikát, csak végrehajtják a kódot.

Gyakran ismételt kérdések

Miben különbözik az XCTest a Quick-től és a Nimble-től?

XCTest — az Apple hivatalos keretrendszere közvetlen Xcode-integrációval. A Quick és a Nimble — harmadik féltől származó könyvtárak, amelyek BDD szintaxist és olvashatóbb asszertációkat biztosítanak. A Quick és a Nimble kényelmes az Acceptance Testinghez, de az XCTest megbízhatóbb az unit-tesztekhez a külső függőségek hiánya miatt.

Hogyan teszteljünk aszinkron kódot az XCTest-ben?

Az aszinkron kód tesztelése XCTestExpectation + `wait(for:timeout:)` vagy az XCTest `async/await` metódusain keresztül történik (iOS 13+). A callback-alapú API-hoz létrejön egy várakozás, amely a lezárásban hívódik meg. Az async/await esetében szabványos asszertációk használatosak az async függvényekben.

Hogyan mock-oljunk függőségeket az XCTest-ben?

Az XCTest nem tartalmaz beépített keretrendszert a mock-okhoz. A mock-olás protokollokon keresztül valósul meg: létrejön egy mock osztály, amely ugyanazt a protokollt implementálja, mint a valós függőség. Az automatikus mock generáláshoz Cuckoo, SwiftyMocky vagy manuális mock-ok használatosak. Dependency Injection inicializátorokon keresztül — kötelező feltétel a teszteléshez.

Futtatható az XCTest valós eszközökön?

Igen, az XCTest valós eszközökön futtatható az Xcode-on vagy az xcodebuild-en keresztül a `-destination 'platform=iOS,name=iPhone 15'` paraméterrel. UI-tesztek valós eszközökön pontosabb eredményeket adnak, mint a szimulátorokon. Az eszközfarmokon történő futtatáshoz BrowserStack, Sauce Labs vagy Firebase Test Lab használatos.

Mi az újdonság a Swift Testing-ben az XCTest-hez képest?

Swift Testing (2024) — új Apple keretrendszer a `@Test`, `@Suite` és `@Expect` makrókkal. Beépített tesztparaméterezést, suite-okba csoportosítást és olvashatóbb szintaxist biztosít. A Swift Testing együtt él az XCTest-tel, és nem váltja fel azt. Az XCTest továbbra is a fő keretrendszer marad az UI-tesztek és teljesítménytesztek számára.

Összefoglalás

  • XCTest — az Apple hivatalos tesztelési keretrendszere, beépítve az Xcode-ba, támogatja a Swift-et és Objective-C-t.
  • XCTestCase biztosítja a setUp/tearDown életciklust és asszertációs készletet az unit-tesztekhez.
  • XCTestExpectation és XCTWaiter — mechanizmusok aszinkron kód teszteléséhez callback és async/await segítségével.
  • Teljesítménytesztek a measure(metrics:) használatával XCTClockMetric, XCTMemoryMetric és XCTCPUMetric támogatással.
  • Asszertációk — XCTAssertEqual, XCTAssertTrue, XCTAssertNil, XCTAssertThrowsError, XCTUnwrap és mások.
  • CI/CD integráció xcodebuild, Xcode Cloud és GitHub Actions segítségével automatikus jelentésgenerálással.
  • Swift Testing — új Apple keretrendszer, amely kiegészíti az XCTest-et unit-tesztekhez és paraméterezéshez.

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is