Section 5/161 menit
5. Confirmation: Testing Callback-Based Code
5. Confirmation: Testing Callback-Based Code
Confirmation adalah cara formal Swift Testing untuk testing kode yang berbasis callback, delegate, atau event-driven.
Sintaks Dasar Confirmation
swift
import Testing
// Test bahwa callback dipanggil tepat 1 kali (default)
@Test
func testCompletionCalled() async {
let service = DataService()
await confirmation("Completion handler dipanggil") { confirm in
service.fetchData { result in
#expect(result != nil)
confirm() // Tandai bahwa expected event terjadi
}
}
}
// Test bahwa callback dipanggil tepat N kali
@Test
func testProgressCallbacks() async {
let uploader = FileUploader()
let expectedCallCount = 5 // Upload 5 file, 5 progress update
await confirmation("Progress dipanggil 5 kali", expectedCount: expectedCallCount) { confirm in
uploader.uploadBatch(files: generateFiles(count: 5)) { progress in
confirm() // Dipanggil setiap ada progress update
}
}
}
// Test bahwa event TIDAK terjadi (expectedCount: 0)
@Test
func testNoErrorCallbackOnSuccess() async {
let service = RobustService()
await confirmation("Error callback tidak dipanggil", expectedCount: 0) { confirm in
service.performOperation(
onSuccess: { /* valid path */ },
onError: { error in
confirm() // Jika ini dipanggil, test gagal (karena expectedCount: 0)
}
)
// Tunggu sebentar untuk memastikan error tidak muncul
try? await Task.sleep(nanoseconds: 100_000_000)
}
}
Confirmation untuk Delegate Pattern
swift
// Testing delegate yang async
protocol DownloadDelegate: AnyObject {
func downloadDidStart()
func downloadDidProgress(fraction: Double)
func downloadDidComplete(data: Data)
func downloadDidFail(error: Error)
}
@Test
func testDelegateCallSequence() async {
class TestDelegate: DownloadDelegate {
var onStart: (() -> Void)?
var onProgress: ((Double) -> Void)?
var onComplete: ((Data) -> Void)?
func downloadDidStart() { onStart?() }
func downloadDidProgress(fraction: Double) { onProgress?(fraction) }
func downloadDidComplete(data: Data) { onComplete?(data) }
func downloadDidFail(error: Error) { Issue.record("Unexpected failure: \(error)") }
}
let delegate = TestDelegate()
let downloader = FileDownloader()
downloader.delegate = delegate
// Verifikasi urutan: start → progress (beberapa kali) → complete
await confirmation("Download dimulai") { confirmStart in
await confirmation("Download selesai") { confirmComplete in
delegate.onStart = { confirmStart() }
delegate.onComplete = { data in
#expect(!data.isEmpty)
confirmComplete()
}
await downloader.download(url: URL(string: "https://example.com/file")!)
}
}
}
Confirmation untuk NotificationCenter
swift
// Testing bahwa notifikasi tertentu di-post
@Test
func testAuthStateChangedNotification() async {
let authManager = AuthManager()
await confirmation("Auth state notification di-post") { confirm in
let observer = NotificationCenter.default.addObserver(
forName: .authStateChanged,
object: nil,
queue: nil
) { notification in
#expect(notification.userInfo?["isLoggedIn"] as? Bool == true)
confirm()
}
defer { NotificationCenter.default.removeObserver(observer) }
await authManager.signIn(username: "test", password: "pass")
}
}