Section 2/161 menit
2. Masalah yang Dipecahkan di Level Lanjutan
2. Masalah yang Dipecahkan di Level Lanjutan
Masalah 1: Callback-Based Code Tidak Bisa Di-test dengan #expect Biasa
Banyak API Apple menggunakan callback (delegate, completion handler, NotificationCenter) yang tidak bisa langsung di-assert dengan #expect.
swift
// ❌ TANPA Confirmation: test tidak menunggu callback — selalu pass palsu
@Test
func testImageDownload() async {
let downloader = ImageDownloader()
var receivedImage: UIImage?
downloader.download(url: testURL) { image in
receivedImage = image // Dipanggil setelah test selesai!
}
// Test sudah selesai sebelum callback dipanggil
#expect(receivedImage != nil) // Selalu gagal atau selalu pass secara tidak deterministik
}
swift
// ✓ DENGAN Confirmation: test menunggu callback dengan jumlah yang tepat
@Test
func testImageDownload() async {
let downloader = ImageDownloader()
await confirmation("Image berhasil didownload") { confirm in
downloader.download(url: testURL) { image in
#expect(image != nil)
confirm() // Sinyal bahwa callback dipanggil
}
}
}
Masalah 2: Bug yang Diketahui Menyebabkan Test Gagal — Tidak Ada Cara Track
Di XCTest, bug yang diketahui biasanya di-comment atau di-skip tanpa tracking. Ini menyebabkan bug terlupakan.
swift
// ❌ TANPA withKnownIssue: bug di-comment — tidak ada tracking
@Test
func testEdgeCaseCalculation() {
let result = Calculator.divide(10, by: 0)
// XCTAssertEqual(result, 0) // Di-comment karena bug #1234 belum fix
// Tidak ada cara tahu kapan bug ini fix dan test harus di-uncomment
}
swift
// ✓ DENGAN withKnownIssue: bug terdokumentasi, test tetap berjalan
@Test
func testEdgeCaseCalculation() {
withKnownIssue("Bug #1234: divide by zero returns NaN, expected 0") {
let result = Calculator.divide(10, by: 0)
#expect(result == 0) // Test tetap berjalan, failure dicatat sebagai "known issue"
}
// Jika bug sudah diperbaiki, withKnownIssue akan melaporkan "known issue unexpectedly passed"
// → sinyal otomatis bahwa bug sudah fix dan blok ini bisa dihapus
}
Masalah 3: Test yang Berjalan Paralel Menyebabkan Race Condition
Swift Testing menjalankan test secara paralel secara default. Test yang share mutable state akan menjadi flaky.
swift
// ❌ TANPA isolasi: state shared antara test yang berjalan paralel
var sharedCounter = 0 // Mutable global state
@Test
func testIncrementA() {
sharedCounter += 1
#expect(sharedCounter == 1) // Flaky! testIncrementB mungkin sudah increment
}
@Test
func testIncrementB() {
sharedCounter += 1
#expect(sharedCounter == 1) // Flaky!
}
swift
// ✓ DENGAN @Suite serialized: pastikan test berjalan serial jika butuh shared state
@Suite(.serialized) // Semua test di suite ini berjalan serial
struct CounterTests {
var counter = 0 // State per-suite — tidak shared antar paralel run
@Test mutating func testIncrementA() {
counter += 1
#expect(counter == 1) // Selalu benar
}
@Test mutating func testIncrementB() {
counter = 0 // Reset untuk test ini
counter += 1
#expect(counter == 1) // Selalu benar
}
}