Paylaşılan eşzamansız fixture hazırlığını Swift Testing paketinin init() async throws metoduna koyun. Swift Testing, bir örnek test metodunu çağırmadan önce bu başlatıcıyı tamamlar; böylece metoda kullanıma hazır bir durum aktarılır. XCTest’te bunun yerine setUp() async throws kullanın.

Bu kılavuz, Xcode’da yerel birim testi verileri hazırlayan Mac geliştiricileri içindir. Amaç, belirleyici hesaplamalar ve sentetik girdiler kullanarak onaylamalar başlamadan önce eşzamansız başlatmayı tamamlamaktır. Apple, başlatıcı yaklaşımını XCTest’ten bir testi taşıma belgesinde açıklıyor.

Swift Testing fixture başlatmasını nasıl bekler?

Bir örnek test metodu için Swift Testing, kapsayıcı paket türünü başlatır ve ardından metodu bu örnek üzerinde çağırır. Paketin argümansız çağrılabilen bir başlatıcısı olmalıdır; bu başlatıcı eşzamansız, hata fırlatan ya da her ikisi birden olabilir. Her örnek test metodu ayrı bir örnek üzerinde çalışır. Bunlar Test işlevlerini paket türleriyle düzenleme belgesinde açıklanan yaşam döngüsü kurallarıdır.

Ortaya çıkan bağımlılık basittir: fixture hazırlığı döner, başlatıcı tamamlanır ve test metodu başlar. Başlatıcınız hazırlık işlemini gerçekten beklemelidir. İçinde yalnızca işi başlatmak bu bağımlılığı kurmaz.

Hazırlığın nereye ait olduğunu seçmek için aşağıdaki karar tablosunu kullanın:

Durum Hazırlığın yeri Hazır olmayı ne sağlar?
Birkaç örnek test aynı fixture tarifine ihtiyaç duyuyor Paket init() async throws Beklenen başlatıcı, her metottan önce tamamlanır
Fixture yalnızca tek bir test için gerekiyor async throws test gövdesi Onaylamalardan önce açık bir try await çağrısı
Mevcut bir test XCTestCase alt sınıfı setUp() async throws XCTest, metottan önce eşzamansız kurulumu tamamlar
Swift Testing testi static ya da genel bir test Test gövdesi veya açıkça çağrılan bir yardımcı Test hazırlığı açıkça bekler

Bu tablo, framework’lerin belgelenmiş yaşam döngüsü kurallarını fixture yerleşimine uygular. Özellikle paket başlatıcısı, örnek başına bir hazırlık noktasıdır; hazırlığın tüm paket için bir kez yapıldığı anlamına gelmez. Apple’ın paket başlatma kurallarına ve XCTest kurulum sırasına bakın.

Xcode’da eksiksiz bir eşzamansız fixture örneği ekleyin

Birlikte gelen Swift Testing desteğiyle Xcode 16 veya daha yenisini kullanın. Swift projesi, Swift Testing’in Swift 6 ve Xcode 16 ile geldiğini ve ek bir paket bağımlılığının gerekmediğini belgeliyor. Resmî Swift Testing README belgesine bakın.

Mevcut birim testi hedefinde File > New > New File From Template seçeneğini seçin, ardından Swift Testing Unit Test şablonunu belirleyin. Oluşturulan dosyanın içeriğini aşağıdaki eksiksiz örnekle değiştirin. Mevcut bir XCTest birim testi paketi Swift Testing testlerini de içerebilir; ayrı bir paket gerekmez. Bu adımlar Apple’ın Xcode projenize test ekleme yönergelerini izler.

import Testing

enum FixtureError: Error {
    case invalidInput
}

private actor SquareCalculator {
    let values: [Int]

    init(values: [Int]) {
        self.values = values
    }

    func squares() -> [Int] {
        values.map { $0 * $0 }
    }
}

struct CalculationFixture {
    let squares: [Int]
    let total: Int

    static func make(values: [Int]) async throws -> Self {
        guard !values.isEmpty,
              values.count <= 100,
              values.allSatisfy({ (0...100).contains($0) }) else {
            throw FixtureError.invalidInput
        }

        let calculator = SquareCalculator(values: values)
        let squares = await calculator.squares()

        return Self(
            squares: squares,
            total: squares.reduce(0, +)
        )
    }
}

@Suite
struct CalculationTests {
    let fixture: CalculationFixture

    init() async throws {
        fixture = try await CalculationFixture.make(values: [2, 4, 6])
    }

    @Test
    func squaresAreReady() {
        #expect(fixture.squares == [4, 16, 36])
    }

    @Test
    func totalIsReady() {
        #expect(fixture.total == 56)
    }
}

Örnek, hesaplamayı yapmak için gerçek bir yerel actor kullanır. Actor yalıtımlı metodunu actor dışından çağırmak await gerektirir. Doğru anda tamamlanması gereken bir gecikme, rastgele girdi, harici bağımlılık veya arka plan işlemi yoktur. Çalıştırma gerçekten askıya alınsın ya da alınmasın, çıktı belirleyici kalır.

Fixture fabrikası boş girdiyi, 100’den fazla değeri ve 0...100 dışındaki değerleri reddeder. Bu örnek sınırlar aritmetiği küçük tutar: her kare en fazla 10.000, toplam ise en fazla 1.000.000 olur. Geçersiz değerler sessizce kaldırılmak veya değiştirilmek yerine hata üretir.

Verilen girdi için beklenen hesaplama 2² + 4² + 6² = 4 + 16 + 36 = 56 olur. Başlatıcı, tamamlanmış fixture’ı isteğe bağlı olmayan bir let özelliğinde saklar. Bu nedenle test metotlarının ne hazır olma bayrağına ne de isteğe bağlı değerin açılmasına ihtiyacı vardır.

Eşzamansız önkoşulları başlatıcıda tamamlandığı için metotların kendileri eşzamanlı kalabilir. Eşzamansız işin test gövdesinin içinde yer alması gerektiğinde Apple’ın belgelenmiş kalıbı, bu işlevi async olarak işaretleyip işlemi doğrudan beklemektir. Eşzamansız kodu test etme belgesine bakın.

Sentetik aritmetik Python ile yerel olarak kontrol edildi. Bu araştırma ortamında Swift bulunmadığından Swift örnekleri incelendi ancak burada derlenip çalıştırılmadı. Yukarıdaki beklenen sonuçlar, örneğin hesaplamasını açıklar; Xcode’da çalıştırılmış bir test sonucu bildirimi değildir.

Görev başlatmak kurulumu neden tamamlamaz?

Yaygın bir hata, eşzamanlı bir başlatıcıdan Task { ... } başlatıp hemen dönmektir. Bu durumda başlatıcı işi başlatmış olur, ancak test metodu başladığında iş hâlâ sürüyor olabilir.

Swift dil kılavuzu, Task { ... } ifadesini yapılandırılmamış bir görev oluşturmak olarak açıklar. Döndürülen tanıtıcı, await handle.value aracılığıyla sonucu beklemek için kullanılabilir. Tanıtıcıyı atmak, bu açık bekleme noktasını ortadan kaldırır. Resmî Swift kitabının Yapılandırılmamış Eşzamanlılık bölümüne bakın.

Fixture başlatma için eşzamansız bir başlatıcıda fabrikayı doğrudan beklemek genellikle bağımlılığı ifade etmenin en açık yoludur. Mevcut bir yardımcı işi kendi içinde başlatıyor ve iş tamamlanmadan dönüyorsa, yardımcıyı beklemek yalnızca dönüşünü bekler. Dönüşün fixture’ın hazır olduğu anlamına gelmesi için tamamlanma sözleşmesini değiştirin veya çağıranın bekleyebileceği bir görev sonucu sunun.

Sabit bir süre uyumak bu bağımlılığı ifade etmez. Yalnızca zamanın geçmesini bekler; hazırlığın bu aralıkta tamamlanıp tamamlanmamasına bağlı olarak hazır olma durumu değişir. Benzer şekilde, test metodunu async yapmak yalnızca eşzamansız çağrılara olanak tanır; metot yine de bağımlı olduğu işlemi beklemelidir.

XCTest’te eşdeğer kurulum nedir?

XCTest, eşzamansız kurulum için özel bir kanca sağlar. Her test metodundan önceki belgelenmiş sıra şöyledir: önce setUp() async throws, sonra setUpWithError(), ardından eşzamanlı setUp(). Test metodu bu kancaları izler. Testlerinizde durumu kurma ve kaldırma belgesine bakın.

Aynı fixture’ı XCTest altında karşılaştırmak için aşağıdaki eksiksiz eşlikçi dosyayı ilk örnekle aynı birim testi hedefine ekleyin. Dosya XCTest’i içe aktarır ve önceden tanımlanmış, modül genelinde görünür CalculationFixture türünü kullanır. Yardımcı tanımlarını ilk dosyada tutun; kopyalamayın.

import XCTest

final class CalculationXCTests: XCTestCase {
    private var fixture: CalculationFixture?

    override func setUp() async throws {
        try await super.setUp()
        fixture = try await CalculationFixture.make(values: [2, 4, 6])
    }

    func testTotalIsReady() throws {
        let readyFixture = try XCTUnwrap(fixture)
        XCTAssertEqual(readyFixture.squares, [4, 16, 36])
        XCTAssertEqual(readyFixture.total, 56)
    }
}

XCTest metodu da eşzamanlı olabilir: eşzamansız hazırlık kurulum sırasında gerçekleşir. İsteğe bağlı özellik, XCTest’in ayrı kurulum aşamasını karşılar; XCTUnwrap ise fixture eksikliğini açık bir başarısızlık hâline getirir. Apple, bu açma kalıbını geçiş kılavuzunda belgeliyor.

Bu testi Swift Testing’e dönüştürürken hazırlığı paket başlatıcısına taşıyın ve import Testing, @Test ile Swift Testing beklentilerini kullanın. Sıradan bir Swift Testing paketinde yalnızca setUp olarak adlandırılmış bir metot, belgelenmiş kurulum mekanizması değildir; Apple’ın geçiş yolu kurulum ailesini başlatmayla değiştirir.

Başlatma hâlâ erken göründüğünde bu sınırları kontrol edin

Önce testin bir örnek metodu olup olmadığını kontrol edin. static testi paket örneği gerektirmez; bu nedenle otomatik örnek başlatmasına bağlı olamaz. Genel bir testin de kapsayıcı örneği yoktur. Her iki biçimde de fixture’ı test gövdesinde oluşturup bekleyin. Desteklenen test biçimleri XCTest’ten bir testi taşıma belgesinde açıklanıyor.

İkinci olarak hazırlık çağrı zincirinin tamamını inceleyin. Hazır durumu gerçekten üreten işlemi bulun ve her çağıranın bunu beklediğinden emin olun. Örnekte actor hesaplaması fabrika dönmeden önce, fabrika ise başlatıcı tamamlanmadan önce biter. Onaylamaların ihtiyaç duyduğu hiçbir iş bu sıralamanın dışında kalmaz.

Üçüncü olarak kurulum hatalarının yukarı iletilmesini sağlayın. CalculationFixture.make hata fırlatırsa paket örneği başlatmasını tamamlayamaz; bu nedenle o örnek üzerindeki test metodu devam edemez. Bu davranış açıkça test edilen şey değilse try? ve bir yedek değer kullanarak başarısız hazırlığı boş fixture ile değiştirmekten kaçının. Örnekteki geçersiz girdi hatası, kullanılabilir görünen bir fixture’ın oluşturulmasını bilerek engeller.

Son olarak başlatma sırasını testlerin zamanlanmasından ayırın. Swift Testing testleri varsayılan olarak paralel çalıştırır. Bir paketin .serialized özelliği, içerdiği testlerin sıralı çalışmasını sağlayabilir; ancak sıralama, beklenmeyen bir görevi beklenen hazırlığa dönüştürmez ve paket başlatıcısının yalnızca bir kez çalışmasını sağlamaz. Apple, bu özelliğin kapsamını Testleri sıralı veya paralel çalıştırma belgesinde açıklıyor.

Bu yerel hesaplama için fixture’ı değişmez tutun ve her örnek test için bağımsız olarak hazırlayın. Temel kontrol bağımlılık zinciridir: hazırlık işlemi tamamlanmış bir fixture döndürür, başlatıcı bu sonucu bekler ve test başlatılmış özelliği okur. Böylece zamanlama varsayımları olmadan somut bir hazır olma koşulu elde edilir.

Kaynaklar