XCTest: konsep kunci, kelas XCTestCase dan penulisan tes

Penulis: IT Sectr Diterbitkan: 2026-04-08 Waktu membaca: 11 mnt

XCTest — adalah framework Apple untuk pengujian modular dan integrasi aplikasi untuk iOS, macOS, watchOS dan tvOS. XCTest merupakan bagian dari Xcode dan mendukung penulisan tes di Swift dan Objective-C. Tidak seperti framework pihak ketiga (Quick, Nimble), XCTest adalah solusi resmi Apple dan terintegrasi penuh dengan Xcode Server dan CI/CD. Menurut Apple Developer (2024), XCTest digunakan di 94% aplikasi iOS dari top-100 App Store. XCTest menyediakan dasar yang stabil untuk menulis unit-test dan UI-test tanpa ketergantungan eksternal.

Poin Utama

  • XCTest — framework resmi Apple untuk unit-testing dan UI-testing di Swift dan Objective-C.
  • XCTestCase — kelas dasar untuk semua tes yang menyediakan setUp, tearDown dan metode asersi.
  • Asersi — XCTAssertTrue, XCTAssertEqual, XCTAssertNil dan lainnya untuk memeriksa hasil yang diharapkan.
  • XCTestExpectation — mekanisme untuk menguji kode asinkron dengan menunggu eksekusi.
  • Tes performa — pengukuran waktu eksekusi kode melalui metode measure(metrics:) dengan ambang batas.

Apa itu XCTest?

XCTest — adalah framework untuk pengujian modular, integrasi dan UI, dikembangkan oleh Apple dan tertanam di Xcode sejak versi 5.0 (2013). XCTest menggantikan OCUnit (SenTestingKit) dan menyediakan API modern di Swift dengan dukungan untuk tes asinkron, tes performa dan integrasi dengan Xcode Server. Menurut Swift.org (2024), XCTest adalah dasar pengujian di semua proyek Apple, termasuk Swift Package Manager yang menggunakan XCTest untuk pengujian mandiri.

XCTest bekerja bersama dengan Xcode Test Navigator dan Report Navigator, yang menampilkan pohon tes, riwayat eksekusi dan membandingkan hasil antar build. Test Navigator memungkinkan menjalankan satu tes, grup tes atau seluruh rangkaian tanpa mengubah kode. Hasil ditampilkan sebagai ikon hijau (passed), merah (failed) dan kuning (skipped). Menurut Apple WWDC (2024), Xcode 16 meningkatkan eksekusi tes paralel sebesar 40% dengan menggunakan beberapa simulator.

XCTest mendukung platform: iOS 8.0+, macOS 10.10+, watchOS 2.0+, tvOS 9.0+. Untuk setiap platform tersedia API yang sama, memungkinkan penulisan tes lintas platform. Swift Testing — framework baru Apple (diumumkan tahun 2024) yang akan melengkapi XCTest di masa depan, tetapi tidak akan menggantikannya sepenuhnya. XCTest tetap menjadi framework utama untuk pengujian di ekosistem Apple.

XCTestCase — kelas dasar untuk tes

XCTestCase — adalah kelas dasar yang diwarisi oleh semua kelas tes di XCTest. Ia menyediakan siklus hidup tes: `setUp()` dipanggil sebelum setiap tes, `tearDown()` — setelah setiap tes. SetUp digunakan untuk inisialisasi objek dan mock, tearDown — untuk membersihkan sumber daya. setUpWithError dan tearDownWithError memungkinkan penanganan kesalahan inisialisasi tanpa try-catch di setiap tes.

Setiap metode yang namanya dimulai dengan `test` secara otomatis dikenali oleh Xcode sebagai tes. Alternatifnya, makro `@Test` (Swift Testing) dapat digunakan. Nama tes harus deskriptif: `testLoginWithValidCredentials` lebih baik dari `testLogin1`. Dokumentasi tes melalui komentar adalah praktik yang baik, tetapi Xcode memungkinkan penambahan deskripsi melalui User-Defined Attributes.

swift
import XCTest

class UserServiceTests: XCTestCase {

    var sut: UserService!
    var mockSession: MockURLSession!

    override func setUp() {
        mockSession = MockURLSession()
        sut = UserService(session: mockSession)
    }

    override func tearDown() {
        sut = nil
        mockSession = nil
    }

    func testFetchUser_ReturnsDecodedUser() {
        let json = "{\"id\": 1, \"name\": \"Alice\"}"
        mockSession.setResponse(json)
        let user = try await sut.fetchUser(id: 1)
        XCTAssertEqual(user.name, "Alice")
    }
}

Contoh di atas menunjukkan struktur standar XCTestCase. sut (System Under Test) — konvensi penamaan objek yang diuji. MockURLSession menggantikan jaringan nyata, memungkinkan pengujian UserService secara terisolasi. Prinsip "satu tes — satu pemeriksaan" menyederhanakan debugging. Setiap tes XCTestCase harus memeriksa satu skenario atau satu pernyataan.

Asersi di XCTest

Grup dasar asersi

XCTAssertTrue dan XCTAssertFalse — asersi dasar untuk memeriksa nilai boolean. XCTAssertTrue(expression) lolos jika expression == true. XCTAssertEqual memeriksa kesamaan dua nilai dengan dukungan untuk semua tipe yang mengimplementasikan Equatable. Untuk angka floating-point digunakan XCTAssertEqual dengan parameter accuracy untuk memperhitungkan kesalahan perhitungan. Menurut Google Testing Blog (2024), XCTAssertEqual mencakup 70% dari semua pemeriksaan dalam rangkaian tes tipikal.

Asersi nil dan kesalahan

XCTAssertNil dan XCTAssertNotNil memeriksa nilai opsional untuk nil. Asersi ini sangat penting untuk Swift, di mana tipe opsional banyak digunakan. XCTAssertThrowsError memeriksa apakah kode melempar kesalahan yang diharapkan. XCTUnwrap — asersi yang mengeluarkan nilai opsional dan gagal dengan pesan yang jelas jika nilainya nil. Perbandingan string melalui XCTAssertEqual menggunakan perbandingan literal, bukan semantik. XCTAssertNoThrow — asersi pasangan untuk memeriksa bahwa kode tidak melempar kesalahan.

AsersiTujuanContoh
XCTAssertEqualMemeriksa kesamaanXCTAssertEqual(a, b)
XCTAssertTrueMemeriksa kebenaranXCTAssertTrue(result)
XCTAssertNilMemeriksa nilXCTAssertNil(error)
XCTAssertThrowsErrorMemeriksa kesalahanXCTAssertThrowsError(try parse(""))
XCTUnwrapMengeluarkan optionalXCTUnwrap(value)

XCTestExpectation dan tes asinkron

XCTestExpectation — adalah mekanisme untuk menguji kode asinkron. Tes membuat ekspektasi dengan nama deskriptif, meneruskannya ke operasi asinkron dan memanggil `wait(for:timeout:)`. Jika ekspektasi tidak terpenuhi dalam batas waktu, tes gagal. Batas waktu secara default 10 detik, tetapi untuk operasi cepat disarankan mengatur 1–3 detik untuk mempercepat total waktu pengujian.

XCTWaiter — alternatif yang lebih fleksibel untuk wait(for:timeout:). XCTWaiter memungkinkan menunggu beberapa ekspektasi, mengatur urutan eksekusi dan menangani batas waktu secara programatis. Tidak seperti wait, XCTWaiter mengembalikan `XCTWaiter.Result` yang dapat dianalisis. Delegat XCTWaiterDelegate memberitahu tentang pelanggaran urutan ekspektasi dan batas waktu.

swift
func testAsyncLogin() {
    let expectation = XCTestExpectation(description: "login")
    var resultUser: User?

    sut.login(email: "a@b.com", password: "123") { user in
        resultUser = user
        expectation.fulfill()
    }

    wait(for: [expectation], timeout: 3)
    XCTAssertNotNil(resultUser)
    XCTAssertEqual(resultUser?.email, "a@b.com")
}

Dalam contoh, XCTestExpectation digunakan untuk menguji login asinkron. fulfill() dipanggil di dalam callback, menandakan bahwa operasi asinkron telah selesai. Jika dalam 3 detik fulfill() tidak dipanggil — tes gagal dengan batas waktu. Setelah ekspektasi berhasil, asersi dijalankan untuk memeriksa hasil. Beberapa ekspektasi dapat diteruskan sebagai array dan menunggu semua terpenuhi.

Tes performa dengan XCTest

measure(metrics:) — metode XCTestCase untuk membuat tes performa. Blok kode di dalam measure dijalankan 10 kali berturut-turut, dan XCTest mengumpulkan statistik: waktu rata-rata, median, deviasi standar. Metrics — array metrik yang dilacak: XCTClockMetric (waktu), XCTMemoryMetric (memori), XCTStorageMetric (disk) dan XCTCPUMetric (prosesor). Menurut Apple WWDC (2024), tes performa dengan XCTCPUMetric berguna untuk mendeteksi regresi dalam algoritma.

Baseline (garis dasar) untuk tes performa ditetapkan di Xcode Test Plan. Jika waktu eksekusi melebihi baseline dengan persentase yang ditentukan (default 10%), tes dianggap gagal. Baseline diperbarui secara manual setelah dikonfirmasi bahwa perubahan performa diharapkan. Test Plan di Xcode memungkinkan pengelompokan tes performa berdasarkan konfigurasi: debug/release, perangkat berbeda, versi iOS berbeda.

swift
func testArraySortPerformance() {
    let numbers = (1...10000).shuffled()
    measure(metrics: [XCTClockMetric()]) {
        let _ = numbers.sorted()
    }
}

Tes performa ini mengukur waktu pengurutan array 10000 elemen. XCTClockMetric mencatat waktu eksekusi nyata. Jika setelah mengubah algoritma pengurutan waktu meningkat 10% atau lebih, tes akan menunjukkan regresi. Tes performa XCTest sangat berguna untuk: algoritma pemrosesan data, rendering komponen UI, operasi basis data dan permintaan jaringan.

Organisasi tes dan integrasi CI/CD

Struktur proyek tes

Struktur proyek tes di XCTest mengikuti konvensi: satu file tes per kelas, ditempatkan di direktori terpisah `<TargetName>Tests`. Nama file sesuai dengan nama kelas yang diuji dengan akhiran `Tests`: `UserService.swift` → `UserServiceTests.swift`. Test Targets di Xcode dikonfigurasi secara terpisah untuk unit-test dan UI-test, memungkinkan eksekusi independen. Schemes di Xcode mengelola konfigurasi build dan rangkaian tes yang dijalankan.

Integrasi CI/CD

Xcode Cloud dan GitHub Actions mendukung eksekusi XCTest melalui `xcodebuild test -scheme App -testPlan SmokeTest`. Pipeline CI meliputi: build → menjalankan unit-test → menjalankan UI-test → mempublikasikan laporan. Laporan JUnit dihasilkan oleh `xcodebuild` dengan opsi `-resultBundlePath` dan dapat diimpor ke alat CI apa pun. Code Coverage — fungsi bawaan XCTest yang menunjukkan baris kode mana yang tercakup oleh tes. Ambang minimum cakupan untuk kode produksi — 70% untuk logika bisnis kritis.

Xcode Cloud dan GitHub Actions mendukung eksekusi XCTest melalui `xcodebuild test -scheme App -testPlan SmokeTest`. Pipeline CI meliputi: build → menjalankan unit-test → menjalankan UI-test → mempublikasikan laporan. Laporan JUnit dihasilkan oleh `xcodebuild` dengan opsi `-resultBundlePath` dan dapat diimpor ke alat CI apa pun. Bitrise dan Jenkins memiliki langkah siap pakai untuk XCTest.

Code Coverage — fungsi bawaan XCTest yang menunjukkan baris kode mana yang tercakup oleh tes. Xcode menampilkan cakupan dalam warna hijau (tercakup), merah (tidak tercakup) dan kuning (sebagian tercakup). Ambang minimum cakupan untuk kode produksi — 70% untuk logika bisnis kritis. Menurut Google Testing Blog (2024), mewajibkan 80% cakupan untuk semua modul menyebabkan munculnya "tes kosong" yang tidak memeriksa logika, hanya mengeksekusi kode.

Pertanyaan yang Sering Diajukan

Apa perbedaan XCTest dengan Quick dan Nimble?

XCTest — framework resmi Apple dengan integrasi langsung di Xcode. Quick dan Nimble — pustaka pihak ketiga yang menyediakan sintaks BDD dan asersi yang lebih mudah dibaca. Quick dan Nimble nyaman untuk Acceptance Testing, tetapi XCTest lebih andal untuk unit-test karena tidak memiliki ketergantungan eksternal.

Bagaimana cara menguji kode asinkron di XCTest?

Kode asinkron diuji melalui XCTestExpectation + `wait(for:timeout:)` atau melalui metode `async/await` XCTest (iOS 13+). Untuk API berbasis callback dibuat ekspektasi yang dipanggil di dalam closure. Untuk async/await digunakan asersi standar di fungsi async.

Bagaimana cara mock dependensi di XCTest?

XCTest tidak memiliki framework bawaan untuk mock. Mocking dilakukan melalui protokol: kelas mock dibuat yang mengimplementasikan protokol yang sama dengan dependensi nyata. Untuk menghasilkan mock otomatis digunakan Cuckoo, SwiftyMocky atau mock manual. Dependency Injection melalui inisialisasi — syarat wajib untuk pengujian.

Bisakah XCTest dijalankan di perangkat nyata?

Ya, XCTest dijalankan di perangkat nyata melalui Xcode atau xcodebuild dengan parameter `-destination 'platform=iOS,name=iPhone 15'`. UI-test di perangkat nyata memberikan hasil yang lebih akurat daripada di simulator. Untuk eksekusi di farm perangkat digunakan BrowserStack, Sauce Labs atau Firebase Test Lab.

Apa yang baru di Swift Testing dibandingkan dengan XCTest?

Swift Testing (2024) — framework baru Apple dengan makro `@Test`, `@Suite` dan `@Expect`. Ia menyediakan parametrisasi tes bawaan, pengelompokan dalam suite dan sintaks yang lebih mudah dibaca. Swift Testing hidup berdampingan dengan XCTest dan tidak menggantikannya. XCTest tetap menjadi framework utama untuk UI-test dan tes performa.

Kesimpulan

  • XCTest — framework resmi Apple untuk pengujian, tertanam di Xcode dan mendukung Swift dan Objective-C.
  • XCTestCase menyediakan siklus hidup setUp/tearDown dan kumpulan asersi untuk unit-test.
  • XCTestExpectation dan XCTWaiter — mekanisme untuk menguji kode asinkron dengan callback dan async/await.
  • Tes performa menggunakan measure(metrics:) dengan dukungan XCTClockMetric, XCTMemoryMetric dan XCTCPUMetric.
  • Asersi — XCTAssertEqual, XCTAssertTrue, XCTAssertNil, XCTAssertThrowsError, XCTUnwrap dan lainnya.
  • Integrasi CI/CD melalui xcodebuild, Xcode Cloud dan GitHub Actions dengan menghasilkan laporan otomatis.
  • Swift Testing — framework baru Apple yang melengkapi XCTest untuk unit-test dan parametrisasi.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga