XCTest: temel kavramlar, XCTestCase sınıfları ve test yazma

Yazar: IT Sectr Yayınlanma: 2026-04-08 Okuma süresi: 11 dk

XCTest, iOS, macOS, watchOS ve tvOS için uygulamaların birim ve entegrasyon testi için Apple framework'üdür. XCTest, Xcode'un bir parçasıdır ve Swift ile Objective-C'de test yazmayı destekler. Üçüncü taraf framework'lerin (Quick, Nimble) aksine XCTest, Apple'ın resmi çözümüdür ve Xcode Server ile CI/CD'ye tamamen entegredir. Apple Developer (2024)'a göre XCTest, App Store'daki ilk 100 iOS uygulamasının %94'ünde kullanılmaktadır. XCTest, harici bağımlılıklar olmadan birim testleri ve kullanıcı arayüzü testleri yazmak için istikrarlı bir temel sağlar.

Önemli Noktalar

  • XCTest — Swift ve Objective-C'de birim testi ve kullanıcı arayüzü testi için Apple'ın resmi framework'ü.
  • XCTestCase — setUp, tearDown ve iddia yöntemlerini sağlayan tüm testler için temel sınıf.
  • İddialar — Beklenen sonuçları doğrulamak için XCTAssertTrue, XCTAssertEqual, XCTAssertNil ve diğerleri.
  • XCTestExpectation — Bekleme ile eşzamansız kod test etme mekanizması.
  • Performans testleri — Eşik değerleriyle measure(metrics:) yöntemiyle kod yürütme süresini ölçme.

XCTest nedir?

XCTest, Apple tarafından geliştirilen ve Xcode'a 5.0 sürümünden (2013) itibaren entegre edilmiş bir birim, entegrasyon ve kullanıcı arayüzü testi framework'üdür. XCTest, OCUnit'in (SenTestingKit) yerini aldı ve eşzamansız testler, performans testleri ve Xcode Server entegrasyonu desteğiyle modern bir Swift API'si sağladı. Swift.org'a (2024) göre XCTest, Swift Package Manager dahil tüm Apple projelerinde testlerin temelidir ve Swift Package Manager, kendi kendini doğrulama için XCTest'i kullanır.

XCTest, Xcode Test Navigator ve Report Navigator ile birlikte çalışarak test ağacını, çalıştırma geçmişini gösterir ve yapılar arasındaki sonuçları karşılaştırır. Test Navigator, kodu değiştirmeden tek bir testi, test grubunu veya tüm paketi çalıştırmaya olanak tanır. Sonuçlar yeşil (geçti), kırmızı (başarısız) ve sarı (atlandı) simgelerle görüntülenir. Apple WWDC (2024)'ye göre Xcode 16, birden çok simülatör kullanarak paralel test yürütmeyi %40 oranında iyileştirdi.

XCTest platformları destekler: iOS 8.0+, macOS 10.10+, watchOS 2.0+, tvOS 9.0+. Her platform aynı API'ye sahiptir ve bu da platformlar arası test yazmayı mümkün kılar. Swift Testing — Apple'ın yeni framework'ü (2024'te duyuruldu) — gelecekte XCTest'i tamamlayacak ancak tamamen yerini almayacaktır. XCTest, Apple ekosisteminde birincil test framework'ü olmaya devam etmektedir.

XCTestCase — testler için temel sınıf

XCTestCase, XCTest'teki tüm test sınıflarının miras aldığı temel sınıftır. Test yaşam döngüsünü sağlar: her testten önce `setUp()` çağrılır, her testten sonra `tearDown()` çağrılır. setUp, nesneleri ve mock'ları başlatmak için kullanılır, tearDown ise kaynakları temizlemek için kullanılır. setUpWithError ve tearDownWithError, her testte try-catch olmadan başlatma hatalarını işlemeye olanak tanır.

Adı `test` ile başlayan her yöntem, Xcode tarafından otomatik olarak bir test olarak tanınır. Alternatif olarak, `@Test` makrosu (Swift Testing) kullanılabilir. Test adları açıklayıcı olmalıdır: `testLoginWithValidCredentials`, `testLogin1`'den daha iyidir. Yorumlar aracılığıyla testlerin belgelenmesi iyi bir uygulamadır, ancak Xcode, Kullanıcı Tanımlı Özellikler aracılığıyla açıklama eklemeye de izin verir.

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

Yukarıdaki örnek, standart XCTestCase yapısını göstermektedir. sut (Sistem Test Altında), test edilen nesne için bir adlandırma kuralıdır. MockURLSession, gerçek ağın yerini alarak UserService'in izole bir şekilde test edilmesini sağlar. “Bir test — bir iddia” ilkesi, hata ayıklamayı basitleştirir: bir test başarısız olursa, geliştirici hangi işlevselliğin bozuk olduğunu hemen bilir. Her XCTestCase testi, bir senaryoyu veya bir iddiayı doğrulamalıdır.

XCTest'te İddialar

Temel İddia Grubu

XCTAssertTrue ve XCTAssertFalse, boolean değerlerini kontrol etmek için temel iddialardır. XCTAssertTrue(expression), expression == true ise geçer. XCTAssertEqual, Equatable'ı uygulayan tüm türleri destekleyerek iki değerin eşitliğini kontrol eder. Kayan noktalı sayılar için, hesaplama hassasiyetini hesaba katmak üzere accuracy parametresiyle XCTAssertEqual kullanılır. Google Testing Blog'a (2024) göre XCTAssertEqual, tipik bir test paketindeki tüm kontrollerin %70'ini kapsar.

Nil İddiaları ve Hatalar

XCTAssertNil ve XCTAssertNotNil, isteğe bağlı değerleri nil için kontrol eder. Bu iddialar, isteğe bağlı türlerin yaygın olarak kullanıldığı Swift'te kritik öneme sahiptir. XCTAssertThrowsError, kodun beklenen bir hata fırlattığını doğrular. XCTUnwrap, isteğe bağlı bir değeri açan ve değer nil ise net bir mesajla başarısız olan bir iddiadır. XCTAssertEqual ile dize karşılaştırması, anlamsal değil, değişmez karşılaştırma kullanır. XCTAssertNoThrow, kodun hata fırlatmadığını doğrulamak için eşleştirilmiş iddiadır.

İddiaAmaçÖrnek
XCTAssertEqualEşitlik kontrolüXCTAssertEqual(a, b)
XCTAssertTrueDoğruluk kontrolüXCTAssertTrue(result)
XCTAssertNilNil kontrolüXCTAssertNil(error)
XCTAssertThrowsErrorHata kontrolüXCTAssertThrowsError(try parse(""))
XCTUnwrapOptional açmaXCTUnwrap(value)

XCTestExpectation ve eşzamansız testler

XCTestExpectation, eşzamansız kodu test etmek için bir mekanizmadır. Test, açıklayıcı bir adla bir beklenti oluşturur, bunu eşzamansız bir işleme iletir ve `wait(for:timeout:)` çağrısı yapar. Beklenti, zaman aşımı içinde karşılanmazsa test başarısız olur. Zaman aşımı varsayılan olarak 10 saniyedir, ancak hızlı işlemler için genel test süresini hızlandırmak için 1-3 saniye ayarlanması önerilir.

XCTWaiter, wait(for:timeout:) için daha esnek bir alternatiftir. XCTWaiter, birden çok beklentiyi beklemeye, yürütme sırasını yapılandırmaya ve zaman aşımlarını programlı olarak işlemeye olanak tanır. wait'in aksine, XCTWaiter analiz edilebilen `XCTWaiter.Result` değerini döndürür. Temsilci XCTWaiterDelegate, beklenti sırası ihlalleri ve zaman aşımları hakkında bildirimde bulunur.

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

Örnekte, XCTestExpectation eşzamansız bir oturum açmayı test etmek için kullanılır. fulfill(), geri arama closure'ı içinde çağrılarak eşzamansız işlemin tamamlandığını bildirir. 3 saniye içinde fulfill() çağrılmazsa, test zaman aşımıyla başarısız olur. Başarılı bekleyişin ardından, sonucu doğrulamak için iddialar gerçekleştirilir. Birden çok beklenti bir dizi olarak iletilebilir ve tümünün tamamlanması beklenebilir.

XCTest ile Performans Testleri

measure(metrics:), performans testleri oluşturmak için bir XCTestCase yöntemidir. measure içindeki kod bloğu art arda 10 kez çalıştırılır ve XCTest istatistikleri toplar: ortalama süre, medyan, standart sapma. Metrikler, izlenen metriklerin bir dizisidir: XCTClockMetric (zaman), XCTMemoryMetric (bellek), XCTStorageMetric (disk) ve XCTCPUMetric (işlemci). Apple WWDC (2024)'ye göre, XCTCPUMetric ile performans testleri algoritmalardaki gerilemeleri tespit etmek için kullanışlıdır.

Performans testleri için temel çizgi Xcode Test Planı'nda ayarlanır. Yürütme süresi, belirlenen bir yüzde (varsayılan %10) kadar temel çizgiyi aşarsa test başarısız kabul edilir. Temel çizgi, performans değişikliğinin beklendiği onaylandıktan sonra manuel olarak güncellenir. Xcode'daki Test Planı, performans testlerini yapılandırmalara göre gruplandırmaya olanak tanır: hata ayıklama/sürüm, farklı cihazlar, farklı iOS sürümleri.

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

Bu performans testi, 10.000 öğelik bir dizinin sıralama süresini ölçer. XCTClockMetric gerçek yürütme süresini yakalar. Sıralama algoritması değiştirildikten sonra süre %10 veya daha fazla artarsa, test bir gerileme olduğunu gösterecektir. XCTest performans testleri özellikle şunlar için kullanışlıdır: veri işleme algoritmaları, kullanıcı arayüzü bileşenlerinin oluşturulması, veritabanı işlemleri ve ağ istekleri.

Test organizasyonu ve CI/CD entegrasyonu

Test projesi yapısı

XCTest'te test projesi yapısı kuralı takip eder: sınıf başına bir test dosyası, ayrı bir `<TargetName>Tests` dizinine yerleştirilir. Dosya adları, `Tests` sonekiyle test edilen sınıf adlarına karşılık gelir: `UserService.swift` → `UserServiceTests.swift`. Xcode'daki Test Hedefleri, birim testleri ve kullanıcı arayüzü testleri için ayrı ayrı yapılandırılır ve bağımsız olarak çalıştırılmalarına olanak tanır. Xcode'daki Şemalar, derleme yapılandırmasını ve çalıştırılacak test kümesini yönetir.

CI/CD entegrasyonu

Xcode Cloud ve GitHub Actions, `xcodebuild test -scheme App -testPlan SmokeTest` aracılığıyla XCTest çalıştırmayı destekler. CI ardışık düzeni şunları içerir: derleme → birim testlerini çalıştırma → kullanıcı arayüzü testlerini çalıştırma → rapor yayınlama. JUnit raporu, `-resultBundlePath` seçeneğiyle `xcodebuild` aracılığıyla oluşturulur ve herhangi bir CI aracına aktarılabilir. Kod Kapsamı, testler tarafından hangi kod satırlarının kapsandığını gösteren yerleşik bir XCTest özelliğidir. Üretim kodu için minimum kapsama eşiği, kritik iş mantığı için %70'tir.

Xcode Cloud ve GitHub Actions, `xcodebuild test -scheme App -testPlan SmokeTest` aracılığıyla XCTest çalıştırmayı destekler. CI ardışık düzeni şunları içerir: derleme → birim testlerini çalıştırma → kullanıcı arayüzü testlerini çalıştırma → rapor yayınlama. JUnit raporu, `-resultBundlePath` seçeneğiyle `xcodebuild` aracılığıyla oluşturulur ve herhangi bir CI aracına aktarılabilir. Bitrise ve Jenkins'in XCTest için hazır adımları vardır.

Kod Kapsamı, testler tarafından hangi kod satırlarının kapsandığını gösteren yerleşik bir XCTest özelliğidir. Xcode, kapsamı yeşil (kapsanan), kırmızı (kapsanmayan) ve sarı (kısmen kapsanan) olarak görüntüler. Üretim kodu kapsamı için minimum eşik, kritik iş mantığı için %70'tir. Google Testing Blog'a (2024) göre, tüm modüller için %80 kapsam zorunlu kılındığında, mantığı doğrulamayan ancak yalnızca kodu çalıştıran “boş testler” ortaya çıkar.

Sıkça Sorulan Sorular

XCTest, Quick ve Nimble'den nasıl farklıdır?

XCTest, Xcode ile doğrudan entegrasyona sahip Apple'ın resmi framework'üdür. Quick ve Nimble, BDD sözdizimi ve daha okunabilir iddialar sağlayan üçüncü taraf kitaplıklardır. Quick ve Nimble, Kabul Testi için uygundur, ancak XCTest, harici bağımlılıkların olmaması nedeniyle birim testleri için daha güvenilirdir.

XCTest'te eşzamansız kod nasıl test edilir?

Eşzamansız kod, XCTestExpectation + `wait(for:timeout:)` veya XCTest'in `async/await` yöntemleri (iOS 13+) aracılığıyla test edilir. Geri arama tabanlı API'ler için, closure'da karşılanan bir beklenti oluşturulur. Async/await için, async işlevlerinde standart iddialar kullanılır.

XCTest'te bağımlılıklar nasıl mock'lanır?

XCTest, yerleşik bir mock'lama framework'ü içermez. Mock'lama, protokoller aracılığıyla uygulanır: gerçek bağımlılıkla aynı protokolü uygulayan bir mock sınıfı oluşturulur. Otomatik mock oluşturma için Cuckoo, SwiftyMocky veya manuel mock'lar kullanılır. Başlatıcılar aracılığıyla bağımlılık enjeksiyonu, test edilebilirlik için zorunlu bir koşuldur.

XCTest gerçek cihazlarda çalıştırılabilir mi?

Evet, XCTest, Xcode veya xcodebuild aracılığıyla `-destination 'platform=iOS,name=iPhone 15'` parametresiyle gerçek cihazlarda çalıştırılır. Gerçek cihazlardaki kullanıcı arayüzü testleri, simülatörlerden daha doğru sonuçlar verir. Cihaz çiftliklerinde çalıştırmak için BrowserStack, Sauce Labs veya Firebase Test Lab kullanılır.

Swift Testing'de XCTest'e kıyasla yeni olan nedir?

Swift Testing (2024), `@Test`, `@Suite` ve `@Expect` makrolarına sahip yeni bir Apple framework'üdür. Yerleşik test parametrelendirmesi, paket gruplaması ve daha okunabilir sözdizimi sağlar. Swift Testing, XCTest ile birlikte var olur ve onun yerini almaz. XCTest, kullanıcı arayüzü testleri ve performans testleri için birincil framework olmaya devam eder.

Özet

  • XCTest — Apple'ın resmi test framework'ü, Xcode'a entegre edilmiş ve Swift ile Objective-C'yi destekler.
  • XCTestCase, birim testleri için setUp/tearDown yaşam döngüsü ve bir dizi iddia sağlar.
  • XCTestExpectation ve XCTWaiter, geri aramalar ve async/await ile eşzamansız kod test etme mekanizmalarıdır.
  • Performans testleri XCTClockMetric, XCTMemoryMetric ve XCTCPUMetric desteğiyle measure(metrics:) kullanır.
  • İddialar — XCTAssertEqual, XCTAssertTrue, XCTAssertNil, XCTAssertThrowsError, XCTUnwrap ve diğerleri.
  • CI/CD entegrasyonu xcodebuild, Xcode Cloud ve GitHub Actions aracılığıyla otomatik rapor oluşturma ile.
  • Swift Testing — birim testleri ve parametrelendirme için XCTest'i tamamlayan yeni bir Apple framework'ü.

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun