Section 4/121 menit

4. Expectations — #expect dan #require

4. Expectations — #expect dan #require

#expect — Soft Assertion (Test Lanjut jika Gagal)

swift
@Test
func userProfile() async throws {
    let user = try await fetchUser(id: "123")
    
    // Test LANJUT meskipun salah satu #expect gagal
    #expect(user.id == "123")          // cek, lanjut
    #expect(!user.name.isEmpty)        // cek, lanjut
    #expect(user.email.contains("@"))  // cek, lanjut
    // Semua failure dikumpulkan — satu run, banyak laporan
}

#require — Hard Assertion (Stop jika Gagal)

swift
@Test
func processOrder() async throws {
    let order = try await fetchOrder(id: "ORD-001")
    
    // Jika ini gagal, test BERHENTI (throw)
    let lineItems = try #require(order.lineItems)
    // lineItems di sini pasti non-nil (unwrapped)
    
    #expect(lineItems.count > 0)
    #expect(lineItems.first?.price ?? 0 > 0)
}

// #require dengan Optional unwrapping
@Test
func configurationLoaded() throws {
    let config = loadConfiguration()
    let apiKey = try #require(config.apiKey)  // unwrap atau stop
    #expect(apiKey.count == 32)
}

Mengharapkan Error

swift
@Test
func divisionByZero() {
    // #expect(throws:) — verifikasi bahwa throw terjadi
    #expect(throws: MathError.divisionByZero) {
        _ = try Calculator.divide(10, by: 0)
    }
}

// Dengan inspeksi error
@Test
func networkFailure() async {
    await #expect(throws: NetworkError.self) {
        try await NetworkClient().fetch(badURL)
    }
}

// Ekspektasi error dengan kondisi lebih spesifik
@Test
func rateLimitError() async throws {
    let error = try await #require(throws: APIError.self) {
        try await client.fetch(rateLimitedEndpoint)
    }
    // error sekarang adalah APIError yang sudah di-unwrap
    guard case .rateLimited(let retryAfter) = error else {
        Issue.record("Expected rateLimited error")
        return
    }
    #expect(retryAfter > 0)
}