Tüm Yazılar
KategoriTesting
Okuma Süresi
14 dk
Yayın Tarihi
2026-04-18
Kelime Sayısı
2.408kelime

Kahveni hazırla - bu içerikli bir makale!

Swift Testing Framework: XCTest'ten Migration Rehberi 2026

Özet

Swift Testing macro-based framework, @Test, #expect, parameterized tests, traits ve XCTest'ten migration — büyük test suite'leri için incremental geçiş rehberi.

  • Büyük test suite'leri XCTest'ten Swift Testing'e en güvenli şekilde incremental migration ile taşınır; iki framework aynı target'ta birlikte çalışır.
  • Tekrarlayan test metodlarını parameterized test'e çevirmek aynı coverage'ı daha az kodla sağlar.
  • 2026 itibarıyla Swift Testing UI testlerini desteklemiyor; XCUIApplication hâlâ XCTest'e bağımlı.
  • Build süresi, test execution, flaky test oranı ve CI maliyetini migration öncesi ve sonrası kendi suite'inde ölç; paylaşılan state'e dokunan testleri .serialized ile işaretle.
Swift Testing Framework: XCTest'ten Migration Rehberi 2026

2024 yılında Apple, WWDC'de Swift Testing'i duyurdu. 2026 başında artık production codebase'lerde ciddi migration'lar başladı. Bu yazı, büyük bir test suite'ini XCTest'ten Swift Testing'e taşırken karşına çıkacak kararları, engelleri ve ölçmen gereken kazanımları ele alıyor.

💡 Pro Tip: Swift Testing ve XCTest bir arada çalışabilir. Büyük codebase'ler için "tam geçiş yerine incremental migration" stratejisi hem riski azaltır hem de team velocity'yi korur.

İçindekiler


Swift Testing Neden Farklı?

XCTest, Objective-C mirasından gelen bir framework. "XCTestCase subclass et, test ile başlayan metod yaz" paradigması 2003'ten beri değişmedi. Swift Testing ise Swift'in macro sistemi üzerine kurulu, modern dil özelliklerini kullanan ground-up bir yeniden yazım.

Temel farklar:

Özellik
XCTest
Swift Testing
Tanımlama
Method naming convention
@Test macro
Assertion
XCTAssert* fonksiyonlar
#expect macro
Parallelism
Default sequential
Default parallel
Parameterized
Yok (elle loop)
arguments: ile native
Trait sistemi
Yok
.serialized, .bug, .tags
Async support
Sınırlı
Full async/await
Error mesajları
Genel
Kaynak kodu gösteren detaylı

@Test ve @Suite Macros

Swift Testing'in temel yapı taşları macro'lar. XCTestCase subclass'ına gerek yok.

swift
1import Testing
2 
3// Basit test — XCTestCase'e gerek yok
4@Test
5func kullaniciBilgileriDogrulansın() {
6 let kullanici = Kullanici(ad: "Muhittin", yas: 28)
7 #expect(kullanici.ad == "Muhittin")
8 #expect(kullanici.yas >= 18)
9}
10 
11// Suite: ilgili testleri grupla
12@Suite("Ödeme İşlemleri")
13struct OdemeTestleri {
14 
15 @Test("Başarılı ödeme akışı")
16 func basariliOdemeAkisi() async throws {
17 let servis = OdemeServisi()
18 let sonuc = try await servis.islem(tutar: 99.99)
19 #expect(sonuc.basarili)
20 #expect(sonuc.transactionId != nil)
21 }
22 
23 @Test("Yetersiz bakiye hatası")
24 func yetersizBakiyeHatasi() async throws {
25 let servis = OdemeServisi()
26 await #expect(throws: OdemeHatasi.yetersizBakiye) {
27 try await servis.islem(tutar: 999_999.99)
28 }
29 }
30}
31 
32// Nested suite — organizasyon için ideal
33@Suite("Kullanıcı Yönetimi")
34struct KullaniciTestleri {
35 
36 @Suite("Kayıt")
37 struct KayitTestleri {
38 @Test func gecerliKayit() { /* ... */ }
39 @Test func eksikEmailHatasi() { /* ... */ }
40 }
41 
42 @Suite("Giriş")
43 struct GirisTestleri {
44 @Test func basariliGiris() { /* ... */ }
45 @Test func yanlisSifreHatasi() { /* ... */ }
46 }
47}

XCTest farkı: XCTest'te her test metodu test prefix'i ile başlamak zorundaydı. Swift Testing'de @Test macro yeterli, metod adı tamamen serbest. Bu özellikle Türkçe metodlarda okunabilirliği artırıyor.


#expect vs XCTAssert: Karşılaştırma

#expect macro, assertion başarısız olduğunda kaynak kodu ve ara değerleri gösterir. XCTAssert sadece "failed" der.

swift
1// XCTest — eski stil
2func testSepetHesaplama() {
3 let sepet = Sepet()
4 sepet.ekle(urun: Urun(fiyat: 29.99))
5 sepet.ekle(urun: Urun(fiyat: 49.99))
6 
7 XCTAssertEqual(sepet.toplam, 79.98, "Toplam yanlış")
8 XCTAssertGreaterThan(sepet.urunSayisi, 0, "Sepet boş")
9 XCTAssertNil(sepet.indirimKodu, "İndirim kodu olmamalı")
10}
11 
12// Swift Testing — modern stil
13@Test("Sepet toplam hesaplama")
14func sepetHesaplama() {
15 let sepet = Sepet()
16 sepet.ekle(urun: Urun(fiyat: 29.99))
17 sepet.ekle(urun: Urun(fiyat: 49.99))
18 
19 // Tek #expect ile birden fazla koşul
20 #expect(sepet.toplam == 79.98)
21 #expect(sepet.urunSayisi > 0)
22 #expect(sepet.indirimKodu == nil)
23}
24 
25// Hata fırlatma kontrolü
26@Test("Geçersiz URL hatası")
27func gecersizURLHatasi() async {
28 await #expect(throws: URLHatasi.gecersizFormat) {
29 try URL(string: "not a url")!.isValid()
30 }
31}
32 
33// Optional unwrapping — #require ile
34@Test("Kullanıcı profil verisi")
35func kullaniciProfilVerisi() throws {
36 let kullanici = oturumYoneticisi.aktifKullanici
37 let profil = try #require(kullanici?.profil) // nil ise test fail
38 #expect(profil.tamAd.isEmpty == false)
39}

Hata mesajı karşılaştırması:

XCTest hatası: XCTAssertEqual failed: ("79.97") is not equal to ("79.98")

Swift Testing hatası:

swift
1Expectation failed: sepet.toplam == 79.98
2 sepet.toplam → 79.97
3 79.98 → 79.98

Swift Testing hangi değerin beklentiden saptığını kaynak konumuyla birlikte gösteriyor. Bu da hatanın kaynağını bulmayı belirgin şekilde hızlandırıyor.


Parameterized Tests: arguments:

XCTest'te parameterized test yoktu. Her input için ayrı metod yazılırdı. Swift Testing'de native destek var.

swift
1// XCTest'teki eski yaklaşım — verbose ve bakımı zor
2func testTurkceKarakter_i() { dogrulaTurkceKarakter("i") }
3func testTurkceKarakter_s() { dogrulaTurkceKarakter("ş") }
4func testTurkceKarakter_g() { dogrulaTurkceKarakter("ğ") }
5// ... 29 Türkçe karakter için 29 metod
6 
7// Swift Testing — tek tanımlama, tüm durumlar
8@Test("Türkçe karakter normalizasyonu", arguments: [
9 ("İstanbul", "istanbul"),
10 ("Şehir", "sehir"),
11 ("Ğuğuş", "gugus"),
12 ("Özel", "ozel"),
13 ("Ümit", "umit"),
14 ("Çalışma", "calisma")
15])
16func turkcseKarakterNormalizasyonu(girdi: String, beklenen: String) {
17 let sonuc = girdi.turkceNormalize()
18 #expect(sonuc == beklenen, "'(girdi)' → '(beklenen)' beklendi, '(sonuc)' geldi")
19}
20 
21// Struct ile kompleks parametre
22struct OdemeSenaryo {
23 let tutar: Double
24 let para_birimi: String
25 let beklenenSonuc: Bool
26}
27 
28@Test("Ödeme senaryoları", arguments: [
29 OdemeSenaryo(tutar: 10.0, para_birimi: "TRY", beklenenSonuc: true),
30 OdemeSenaryo(tutar: 0.0, para_birimi: "TRY", beklenenSonuc: false),
31 OdemeSenaryo(tutar: -5.0, para_birimi: "USD", beklenenSonuc: false),
32 OdemeSenaryo(tutar: 99.99, para_birimi: "EUR", beklenenSonuc: true)
33])
34func odemeSenaryo(senaryo: OdemeSenaryo) async throws {
35 let servis = OdemeServisi()
36 let sonuc = await servis.dogrula(tutar: senaryo.tutar, paraBirimi: senaryo.para_birimi)
37 #expect(sonuc == senaryo.beklenenSonuc)
38}
39 
40// Cartesian product — iki dizi kombinasyonu
41@Test("Platform x Dil kombinasyonları", arguments: ["iOS", "macOS", "watchOS"], ["tr", "en", "de"])
42func platformDilKombinasyonu(platform: String, dil: String) {
43 let konfigurasyon = AppKonfigurasyonu(platform: platform, dil: dil)
44 #expect(konfigurasyon.gecerli)
45}
46// Bu test 3x3=9 farklı kombinasyonu otomatik test eder

Tekrarlayan test metodlarını parameterized test'e dönüştürmek aynı coverage'ı daha az satırla sağlar.


Traits: .serialized, .bug(), .tags()

Trait sistemi test davranışını meta-level'da kontrol etmek için kullanılıyor.

swift
1// .serialized — suite'i sıralı çalıştır (database testleri için kritik)
2@Suite("Veritabanı İşlemleri", .serialized)
3struct VeritabaniTestleri {
4 
5 @Test func kayitEkle() async throws { /* ... */ }
6 @Test func kayitGuncelle() async throws { /* ... */ }
7 @Test func kayitSil() async throws { /* ... */ }
8 // Bu testler sırayla çalışır — race condition yok
9}
10 
11// .bug() — bilinen hata ile ilişkilendir
12@Test("Çift tıklama race condition", .bug("https://github.com/sirket/uygulama/issues/1234"))
13func ciftTiklamaRaceCondition() async {
14 // Bu test şu an failing — issue link ile takip ediliyor
15 let buton = CiftTiklamaKorunaklıButon()
16 async let tiklama1 = buton.tikla()
17 async let tiklama2 = buton.tikla()
18 let sonuclar = await [tiklama1, tiklama2]
19 #expect(sonuclar.filter(.islemGerceklesti).count == 1)
20}
21 
22// .tags() — kategori bazlı filtreleme
23extension Tag {
24 @Tag static var kritik: Self
25 @Tag static var smoke: Self
26 @Tag static var entegrasyon: Self
27 @Tag static var regresyon: Self
28}
29 
30@Test("Giriş akışı smoke test", .tags(.smoke, .kritik))
31func girisAkisSmokeTest() async throws { /* ... */ }
32 
33@Test("Ödeme entegrasyon testi", .tags(.entegrasyon))
34func odemeEntegrasyonTesti() async throws { /* ... */ }
35 
36// CI'da sadece smoke testleri çalıştır:
37// xcodebuild test -filter-tag smoke
38 
39// .enabled(if:) — koşullu test
40@Test("Face ID testi", .enabled(if: BiometriYoneticisi.faceIDMevcut))
41func faceIDTesti() async throws { /* ... */ }
42 
43// .disabled — geçici olarak devre dışı bırak
44@Test("Flaky network test", .disabled("Intermittent CI failures — FB12345678"))
45func flakyNetworkTest() async throws { /* ... */ }

Async Test Support

Swift Testing, async/await'i first-class citizen olarak destekliyor. XCTest'teki expectation(description:) kalabalığı tamamen ortadan kalkıyor.

swift
1// XCTest'teki async test — verbose
2func testAsyncVeriYukleme() {
3 let expectation = XCTestExpectation(description: "Veri yüklendi")
4 
5 Task {
6 let veri = await servis.yukle()
7 XCTAssertFalse(veri.isEmpty)
8 expectation.fulfill()
9 }
10 
11 wait(for: [expectation], timeout: 5.0)
12}
13 
14// Swift Testing — temiz async/await
15@Test("Async veri yükleme")
16func asyncVeriYukleme() async throws {
17 let veri = try await servis.yukle()
18 #expect(veri.isEmpty == false)
19}
20 
21// Concurrent işlem testi
22@Test("Paralel API çağrıları")
23func paralelAPIcagrisi() async throws {
24 async let kullanici = apiServis.getKullanici(id: "user1")
25 async let urunler = apiServis.getUrunler()
26 async let siparisler = apiServis.getSiparisler(kullaniciId: "user1")
27 
28 let (k, u, s) = try await (kullanici, urunler, siparisler)
29 
30 #expect(k.id == "user1")
31 #expect(u.count > 0)
32 #expect(s.isEmpty || s.first?.kullaniciId == k.id)
33}
34 
35// Actor ile thread-safe test
36@Test("Actor izolasyon kontrolü")
37func actorIzolasyonKontrol() async {
38 let sayac = GuvenliSayac()
39 
40 await withTaskGroup(of: Void.self) { grup in
41 for _ in 0..<1000 {
42 grup.addTask { await sayac.artir() }
43 }
44 }
45 
46 let deger = await sayac.deger
47 #expect(deger == 1000)
48}

Setup/Teardown: init/deinit Paradigması

XCTest'teki setUp()/tearDown() yerine Swift Testing'de init ve deinit kullanılıyor. Bu yaklaşım daha Swift-native ve dependency injection için çok daha temiz.

swift
1// XCTest — eski setup/teardown
2class AgPaylaşimTestleri: XCTestCase {
3 var servis: AgServisi!
4 var mockNW: MockNetworkMonitor!
5 
6 override func setUp() {
7 super.setUp()
8 mockNW = MockNetworkMonitor()
9 servis = AgServisi(monitor: mockNW)
10 }
11 
12 override func tearDown() {
13 servis = nil
14 mockNW = nil
15 super.tearDown()
16 }
17}
18 
19// Swift Testing — init/deinit ile temiz DI
20@Suite("Ağ Servisi Testleri")
21struct AgServisTestleri {
22 let servis: AgServisi
23 let mockMonitor: MockNetworkMonitor
24 
25 init() {
26 mockMonitor = MockNetworkMonitor()
27 servis = AgServisi(monitor: mockMonitor)
28 }
29 
30 // deinit — cleanup gerekiyorsa
31 // (struct'ta deinit yok, class kullan)
32 
33 @Test("Çevrimiçi durumu")
34 func cevrimiciDurumu() async {
35 mockMonitor.durum = .baglı
36 let sonuc = await servis.baglantiKontrol()
37 #expect(sonuc == .baglı)
38 }
39 
40 @Test("Çevrimdışı fallback")
41 func cevrimdisiFallback() async {
42 mockMonitor.durum = .bağlantıKesik
43 let sonuc = await servis.baglantiKontrol()
44 #expect(sonuc == .bağlantıKesik)
45 }
46}
47 
48// Async init — veritabanı bağlantısı için
49@Suite("Veritabanı Entegrasyon Testleri", .serialized)
50final class VTEntegrasyonTestleri {
51 let db: TestVeritabani
52 
53 init() async throws {
54 db = try await TestVeritabani.baglaN()
55 try await db.semasıOlustur()
56 try await db.ornekVeriEkle()
57 }
58 
59 deinit {
60 // Cleanup — test sonrası temizle
61 Task { try? await db.temizle() }
62 }
63 
64 @Test func kullanicEkle() async throws {
65 let kullanici = KullaniciOlusturma(ad: "Test", email: "test@test.com")
66 let eklenen = try await db.kullanici.ekle(kullanici)
67 #expect(eklenen.id != nil)
68 }
69}

Migration Stratejisi: Incremental Yaklaşım

Binlerce testlik bir suite'i bir gecede geçirmeye çalışmak başlı başına bir proje anlamına gelir. Incremental migration hem riski hem maliyeti azaltır.

Faz 1: Coexistence Setup (1-2 gün)

XCTest ve Swift Testing aynı target'ta birlikte çalışabilir. Import yeterli.

swift
1// Mevcut XCTestCase dosyası dokunulmaz
2class EskiTestler: XCTestCase {
3 func testEskiIslevsellik() { /* değişmedi */ }
4}
5 
6// Yeni dosyada Swift Testing
7import Testing
8 
9@Test("Yeni özellik testi")
10func yeniOzellikTesti() { /* Swift Testing */ }

Faz 2: Yeni testler Swift Testing ile yaz (ongoing)

Her yeni test Swift Testing formatında. Mevcut testlere dokunma.

Faz 3: Kolay migrate edilebilir testleri geçir

Unit test, basit assertion, XCTAssertEqual/NotNil olan dosyalardan başla. Converter script işe yarıyor:

bash
1#!/bin/bash
2# Basit XCTest -> Swift Testing dönüşüm heuristic'i
3# (Manuel review zorunlu — otomatik geçiş %70 doğru)
4sed -i '' 's/XCTAssertEqual(\(.*\), \(.*\))/#expect(\1 == \2)/g' "$1"
5sed -i '' 's/XCTAssertNil(\(.*\))/#expect(\1 == nil)/g' "$1"
6sed -i '' 's/XCTAssertNotNil(\(.*\))/#expect(\1 != nil)/g' "$1"
7sed -i '' 's/XCTAssertTrue(\(.*\))/#expect(\1)/g' "$1"
8sed -i '' 's/XCTAssertFalse(\(.*\))/#expect(!(\1))/g' "$1"

Faz 4: XCTestSourceLocationAttached uyumluluğu

Bazı test infrastructure araçları XCTest'e bağımlı. Swift Testing bağlamında XCTest assertion'larına ihtiyaç duyulabilir:

swift
1// XCTest bridge — her ikisini de çağırmak gerektiğinde
2import XCTest
3import Testing
4 
5@Test("Eski infrastructure uyumlu test")
6func eskiInfrastrukturUyumlu() {
7 let sonuc = hesapla(5, 3)
8 
9 // Swift Testing assertion
10 #expect(sonuc == 8)
11 
12 // Eski raporlama aracı için XCTest assertion da çalışır
13 XCTAssertEqual(sonuc, 8)
14}

Faz 5: Parallelism optimizasyonu

Swift Testing default olarak paralel çalışıyor. Race condition olan testleri .serialized ile işaretle.


UI Test Gap: Hala XCTest Gerekli

🚨 Kritik bilgi: Swift Testing, 2026 itibarıyla UI testleri desteklemiyor. XCUIApplication, XCUIElement gibi UI test API'leri XCTest'e bağımlı ve Swift Testing'e geçirilmedi.

swift
1// Bu hala XCTestCase ile yazılmalı
2class GirisEkraniUITestleri: XCTestCase {
3 func testBasariliGirisAkisi() {
4 let uygulama = XCUIApplication()
5 uygulama.launch()
6 
7 let emailAlani = uygulama.textFields["Email"]
8 emailAlani.tap()
9 emailAlani.typeText("test@example.com")
10 
11 let sifreAlani = uygulama.secureTextFields["Şifre"]
12 sifreAlani.tap()
13 sifreAlani.typeText("gizli123")
14 
15 uygulama.buttons["Giriş Yap"].tap()
16 
17 XCTAssertTrue(uygulama.staticTexts["Ana Sayfa"].waitForExistence(timeout: 3))
18 }
19}

Apple'ın roadmap'ine göre Swift Testing UI desteği iOS 19 / Xcode 17 döneminde gelebilir. Şu an hybrid yapı kaçınılmaz.


Xcode Cloud + Test Plan v2

Swift Testing, Test Plan v2 formatını gerektiriyor. Xcode 15.3+ ile geliyor.

json
1// TestPlan.xctestplan — Swift Testing dahil
2{
3 "configurations": [
4 {
5 "id": "smoke",
6 "name": "Smoke Tests",
7 "options": {
8 "testTimeoutsEnabled": true,
9 "defaultTestExecutionTimeAllowance": 30
10 },
11 "testTargets": [
12 {
13 "target": {
14 "name": "UygulamaTests",
15 "blueprintName": "UygulamaTests"
16 },
17 "selectedTests": [],
18 "skippedTests": [],
19 "tagFilters": {
20 "enabled": true,
21 "matchers": [{ "tagName": "smoke" }]
22 }
23 }
24 ]
25 }
26 ]
27}

Xcode Cloud workflow entegrasyonu:

yaml
1# ci_scripts/ci_post_xcodebuild.sh
2#!/bin/sh
3# Swift Testing result parser — custom reporting
4if [ "$CI_XCODEBUILD_ACTION" = "test" ]; then
5 echo "Test tamamlandı. Swift Testing + XCTest sonuçları birleştiriliyor..."
6 # xcresulttool ile sonuç işleme
7 xcrun xcresulttool get --format json --path "$CI_RESULT_BUNDLE_PATH" > test_results.json
8fi

Performance: Neyi Ölçmeli?

Migration öncesi ve sonrası kendi suite'inde karşılaştırman gereken metrikler:

Metrik
Neden önemli
Nasıl ölçülür
Clean build
Macro expansion ve test target'ının derleme maliyeti
xcodebuild clean build-for-testing süresi
Incremental build
Günlük geliştirme döngüsü
Tek dosya değişikliği sonrası build-for-testing süresi
Test execution (seri)
Karşılaştırma için taban çizgisi
xcodebuild test-without-building süresi
Test execution (paralel)
Swift Testing'in varsayılan paralel çalıştırması
Aynı komut, paralel çalıştırma açıkken
Memory (test runner)
CI makinesinin boyutlandırılması
CI agent metrikleri ya da Instruments

Compile time tarafında beklenti, XCTestCase subclass hiyerarşisinin (tip kontrolü ve vtable maliyeti) struct-based yapıyla hafiflemesi; ama macro expansion da maliyet ekler, bu yüzden sonucu kendi suite'inde ölç.

Swift Testing testleri varsayılan olarak paralel çalıştırır ve kazancın en büyük kısmı genelde buradan gelir; paylaşılan state'e dokunan testleri ise .serialized ile işaretlemen gerekir.


🏆 Migration Sonrası İzlenecek Çıktılar

Geçişin işe yarayıp yaramadığını görmek için ilk birkaç ay şu göstergeleri takip et:

  • Flaky test oranı: paralel çalıştırma gizli paylaşılan-state bug'larını erken yüzeye çıkarır; oran önce artıp sonra düşebilir
  • Test yazma süresi: parameterized test ve temiz DI ile yeni test başına harcanan süre
  • CI maliyeti: paralel execution'ın makine süresine etkisi
  • Onboarding süresi: yeni geliştiricilerin test framework'üne alışma süresi

🥚 Gizli Özellik: Confirmation API

Henüz çok az konuşulan bir özellik: confirmation() API, callback-based async işlemleri test etmek için.

swift
1@Test("Bildirim yayınlandı")
2func bildirimYayinlandi() async throws {
3 try await confirmation("Bildirim en az bir kez yayınlanmalı") { onayla in
4 let abonelik = NotificationCenter.default.addObserver(
5 forName: .kullaniciBildirim, object: nil, queue: nil
6 ) { _ in
7 onayla()
8 }
9 
10 defer { NotificationCenter.default.removeObserver(abonelik) }
11 
12 await bildirimiTetikle()
13 }
14}

confirmation() ayrıca expectedCount parametresi ile kaç kez çağrılması gerektiğini de doğrulayabilir.


🎁 Bonus: XCTest → Swift Testing Cheatsheet

swift
1XCTAssertEqual(a, b) → #expect(a == b)
2XCTAssertNotEqual(a, b) → #expect(a != b)
3XCTAssertNil(x) → #expect(x == nil)
4XCTAssertNotNil(x) → #expect(x != nil)
5XCTAssertTrue(cond) → #expect(cond)
6XCTAssertFalse(cond) → #expect(!cond)
7XCTAssertGreaterThan(a, b) → #expect(a > b)
8XCTAssertThrowsError(try f()) → #expect(throws: Error.self) { try f() }
9XCTUnwrap(optional) → try #require(optional)
10XCTSkip("neden") → throw XCTSkip("neden") (hala XCTest)
11setUp() → init()
12tearDown() → deinit (class'ta)

Sonuç ve Tavsiyeler

Swift Testing, XCTest'in doğal halefi. 2026 itibarıyla yeni testlerin %100'ünü Swift Testing ile yazmak öneriyorum. Mevcut codebase için incremental migration:

  1. Bugün başla: Yeni testleri Swift Testing ile yaz
  2. Düşük asılı meyve: Parameterized'a dönüştürülebilecek XCTest metodlarını belirle
  3. UI testlere dokunma: Apple'ın roadmap'ini bekle
  4. Trait'leri kullan: Özellikle .tags() ile CI pipeline'ını optimize et
  5. Parallelism dikkat: Race condition'lı testleri .serialized ile işaretle

Daha fazlası için Swift 6 yeniliklerine, iOS 19 beta değerlendirmesine ve SwiftUI vs UIKit 2026 rehberine bakabilirsiniz.

Kaynaklar:

Etiketler

#Swift Testing#XCTest#Testing#Migration#Macros#iOS#2026
Muhittin Çamdalı

Muhittin Çamdalı

Senior Mobile Engineer

12+ yıllık deneyime sahip Senior Mobile Engineer. iOS, Flutter ve React Native ile mobil ürünler geliştiriyorum; full-stack ve AI-native çalışıyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Onay e-postasındaki bağlantıyı açıp “Aboneliğimi onayla” düğmesine bastığında aboneliğin başlar. Bültende açılma/tıklama istatistikleri tutulur; dilediğin an tek tıkla ayrılabilirsin. Gizlilik

Paylaş

İlgili İçerik