Episode ini membahas quality assurance di Swift: unit testing dengan XCTest, UI testing dan snapshot testing, mocking dependency dengan test doubles, serta pengaturan continuous integration untuk project Swift agar kualitas terjamin secara otomatis.

Test bukan pajak yang harus dibayar — mereka jaring pengaman yang membiarkan kalian mengubah kode dengan percaya diri. Episode 15 membahas testing dan quality assurance di Swift: unit testing dengan XCTest, UI testing dan snapshot testing, mocking dependency, serta continuous integration agar kualitas terjaga di setiap perubahan.
Kombinasi test yang baik dan CI yang menjalankannya secara otomatis mengubah cara tim bekerja: bug ditemukan dalam menit setelah kode masuk, bukan minggu kemudian di tangan pengguna.
XCTest adalah framework testing standar Apple. Package SPM dari episode 10 sudah menyertakan test target; test ditulis dalam class yang mewarisi XCTestCase:
import XCTest
final class KalkulatorTests: XCTestCase {
func testTambahPositif() {
let hasil = tambah(2, 3)
XCTAssertEqual(hasil, 5)
}
func testTambahNegatif() {
XCTAssertEqual(tambah(-1, 1), 0)
}
}XCTAssertEqual(hasil, 5) membandingkan nilai aktual dan harapan. Nama test testTambahPositif mengikuti konvensi yang terlihat jelas di laporan. Setiap test berjalan independen — gagalnya satu tidak memengaruhi yang lain.
Test dijalankan dari terminal atau Xcode:
swift testswift test membangun package dan menjalankan semua test di test target. Untuk package library, ini cara tercepat memvalidasi perubahan. Di Xcode, tekan Cmd-U untuk menjalankan test target aktif.
XCUITest menguji aplikasi dari luar — seperti pengguna mengetuk dan menggeser layar sungguhan:
final class AplikasiUITests: XCTestCase {
func testLoginTampil() {
let app = XCUIApplication()
app.launch()
let tombol = app.buttons["loginButton"]
XCTAssertTrue(tombol.exists)
tombol.tap()
}
}app.buttons["loginButton"] mencari elemen UI berdasarkan accessibility identifier, lalu tombol.tap() mensimulasikan ketukan. UI test lambat dan rentan terhadap perubahan tata letak — gunakan untuk alur penting seperti login dan checkout, bukan untuk setiap halaman.
Snapshot testing membandingkan tampilan UI dengan gambar referensi:
swift test --filter SnapshotTestsswift test --filter SnapshotTests menjalankan hanya test yang cocok dengan filter. Snapshot berfungsi seperti test visual: tampilan yang berubah tanpa disengaja langsung terdeteksi. Perbarui snapshot secara eksplisit saat perubahan tampilan memang disengaja — jangan pernah memperbarui tanpa meninjau diff-nya.
Test unit harus berjalan cepat dan deterministik — tanpa jaringan nyata, waktu nyata, atau data acak. Caranya dengan test doubles: objek tiruan yang menggantikan dependency asli. Contoh dengan protocol sebagai kontrak:
protocol LayananJaringan {
func ambilData() async throws -> Data
}
struct LayananAsli: LayananJaringan {
func ambilData() async throws -> Data {
let (data, _) = try await URLSession.shared.data(
from: URL(string: "https://api.example.com")!)
return data
}
}
struct LayananTiruan: LayananJaringan {
var hasilData: Data
func ambilData() async throws -> Data {
return hasilData
}
}struct LayananTiruan: LayananJaringan mengimplementasikan kontrak yang sama tanpa jaringan. Kode produksi bergantung pada protocol, sehingga test bisa menyuntikkan tiruan kapan pun dibutuhkan — pola ini membuat logika yang diuji bebas dari faktor eksternal.
Kenali empat jenis utama:
CI menjalankan build dan test pada setiap push. Untuk project server-side Swift, workflow-nya sederhana:
name: CI
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: swift-actions/setup-swift@v2
with:
swift-version: "6.0"
- run: swift build
- run: swift testuses: swift-actions/setup-swift@v2 menginstall Swift toolchain di runner CI. Untuk aplikasi iOS, build dilakukan dengan xcodebuild test di runner macOS, dan episode 18 akan membahas tooling build secara menyeluruh.
Kualitas yang konsisten butuh standar yang dijalankan otomatis:
Tip
Mulai CI sejak awal project, bukan setelah besar. Otomatisasi kecil yang berjalan dari hari pertama jauh lebih mudah dijaga daripada merekayasa ulang pipeline ketika project sudah rumit.
Inti yang harus dibawa pulang:
XCTAssertEqual dan rekan-rekannya.swift test menjalankan seluruh test package dari terminal.Di episode 16 selanjutnya kita akan membahas architecture dan design patterns — MVC, MVVM, MVP, dan Clean Architecture di Swift, protocol-oriented design dan dependency injection, pola coordinator untuk navigasi, serta state management dengan Combine dan SwiftUI. Arsitektur kalian akan bertahan seiring aplikasi membesar!