Agar setiap skenario memiliki hasil dan kontrol untuk dijalankan ulang sendiri di Xcode, pindahkan pengujian unit XCTest berbasis loop ke @Test berparameter milik Swift Testing. Panduan ini menggunakan perhitungan tata letak ubin lokal untuk menunjukkan proses migrasi dan memverifikasi perilaku pelaporannya.
Mengapa loop XCTest tidak melaporkan setiap skenario secara terpisah?
XCTest menemukan metode pengujian pada subclass XCTestCase. Metode tersebut tidak menerima parameter dan namanya diawali dengan test. Loop di dalam satu metode yang ditemukan tetap menjadi bagian dari metode tersebut; iterasinya tidak menjadi pengujian yang ditemukan secara terpisah. Menambahkan nama skenario ke suatu pernyataan dapat memperjelas diagnostik, tetapi tidak membuat kontrol untuk menjalankannya sendiri. Lihat Mendefinisikan Kasus dan Metode Pengujian dari Apple.
Siklus hidup mengikuti batas yang sama. XCTest menjalankan metode penyiapan instans sebelum setiap metode pengujian dan metode pembongkarannya setelah itu. Karena itu, loop dengan lima iterasi tidak otomatis menerima lima siklus penyiapan dan pembongkaran. Jika suatu iterasi mengubah fixture, iterasi berikutnya mungkin mewarisi keadaan tersebut kecuali pengujian meresetnya secara eksplisit. Apple mendokumentasikan urutan ini dalam Menyiapkan dan Membongkar Keadaan dalam Pengujian Anda.
Swift Testing menyediakan hasil yang dibutuhkan di sini: satu fungsi menerima argumen skenario, dan runner memperlakukan pemanggilannya sebagai kasus yang independen. Xcode menampilkan argumennya dan menyediakan kontrol untuk menjalankan tiap kasus sendiri. Apple menunjukkan perilaku ini dalam Mengembangkan Swift Testing Lebih Lanjut.
Perbedaan ini penting saat mendiagnosis kegagalan. Kegagalan pernyataan dan penghentian dini merupakan peristiwa yang berbeda: loop dapat terus memeriksa setelah pernyataan biasa, sedangkan error yang dilemparkan atau return eksplisit dapat mencegah iterasi berikutnya dijalankan. Memisahkan skenario menjadi beberapa kasus menghilangkan alur kendali bersama di antara skenario. Namun, cara ini tidak membuat kegagalan yang menghentikan proses bisa dipulihkan.
Siapkan target pengujian unit yang ada
Gunakan Xcode 16 atau versi lebih baru untuk alur kerja ini. Swift Testing disertakan dalam distribusi Xcode tersebut dan toolchain Swift.org mulai Swift 6.0. Proyek Swift merekomendasikan penggunaan salinan bawaan untuk pekerjaan pengujian biasa; contoh ini tidak memerlukan dependensi paket eksternal. Lihat Mendapatkan Swift Testing.
Pertahankan bundel pengujian unit yang ada. Apple secara eksplisit mendukung Swift Testing dan XCTest dalam target yang sama, sehingga migrasi bertahap dapat dimulai dengan satu file Swift baru. Di Xcode, pilih File > New > New File From Template, pilih Swift Testing Unit Test, lalu tambahkan file tersebut ke target pengujian unit yang ada. Jika proyek belum memiliki target pengujian, buat Unit Testing Bundle melalui File > New > Target. Langkah-langkah ini didokumentasikan dalam Menambahkan pengujian ke proyek Xcode Anda.
Panduan ini menguji kode perhitungan secara langsung. Panduan ini tidak mengotomatiskan jendela desktop. Jalur yang didokumentasikan Apple untuk otomasi UI tetap menggunakan XCTest; gunakan pendekatan berparameter ini untuk logika dasar yang menentukan tata letak. Panduan menambahkan pengujian yang sama menjelaskan batas kerangka kerja tersebut.
Jadikan setiap skenario satu rekaman argumen lengkap
Misalkan sebuah app Mac menyusun ubin dalam baris. Dengan empat kolom, nol ubin memerlukan nol baris, empat ubin memenuhi satu baris, dan lima ubin memerlukan dua baris. Tujuan konkretnya adalah mempertahankan pemeriksaan tersebut sekaligus membuat setiap skenario terlihat dan dapat dijalankan sendiri.
Gunakan satu rekaman yang memuat nama skenario, input, dan output yang diharapkan. Dengan demikian, hasil yang diharapkan tetap terkait dengan inputnya ketika kasus ditambahkan atau diurutkan ulang. Lima rekaman berikut adalah data pengujian ilustratif, bukan hasil pengamatan dari aplikasi yang sudah ada.
| Skenario | Jumlah ubin | Kolom | Baris yang diharapkan | Tujuan |
|---|---|---|---|---|
empty |
0 | 4 | 0 | Input kosong |
one-tile |
1 | 4 | 1 | Baris pertama terisi sebagian |
exact-row |
4 | 4 | 1 | Batas tepat |
wrap |
5 | 4 | 2 | Ubin pertama setelah batas |
two-full-rows |
8 | 4 | 2 | Kelipatan tepat |
Tempatkan file lengkap dan mandiri ini di target pengujian unit. File ini menyertakan implementasi sintetis sehingga dapat dicoba tanpa modul app atau file lain. File ini tidak menggunakan layanan, mock, file, atau akses jaringan.
import Testing
private struct TileLayout {
func rowCount(tileCount: Int, columns: Int) -> Int {
precondition(tileCount >= 0)
precondition(columns > 0)
let fullRows = tileCount / columns
let partialRow = tileCount % columns == 0 ? 0 : 1
return fullRows + partialRow
}
}
private struct LayoutScenario:
Codable, Sendable, CustomTestStringConvertible {
let name: String
let tileCount: Int
let columns: Int
let expectedRows: Int
var testDescription: String { name }
static let examples: [LayoutScenario] = [
.init(name: "empty", tileCount: 0,
columns: 4, expectedRows: 0),
.init(name: "one-tile", tileCount: 1,
columns: 4, expectedRows: 1),
.init(name: "exact-row", tileCount: 4,
columns: 4, expectedRows: 1),
.init(name: "wrap", tileCount: 5,
columns: 4, expectedRows: 2),
.init(name: "two-full-rows", tileCount: 8,
columns: 4, expectedRows: 2)
]
}
struct TileLayoutTests {
@Test("Tile rows", arguments: LayoutScenario.examples)
fileprivate func rowCountMatchesScenario(
_ scenario: LayoutScenario
) {
let layout = TileLayout()
let actualRows = layout.rowCount(
tileCount: scenario.tileCount,
columns: scenario.columns
)
#expect(actualRows == scenario.expectedRows)
}
}
Migrasi memindahkan iterasi ke @Test(arguments:): setiap elemen menjadi argumen untuk satu pemanggilan. Codable menyediakan dukungan encoding untuk menjalankan ulang kasus tertentu, sedangkan CustomTestStringConvertible menyediakan label skenario yang mudah dibaca. Apple mendokumentasikan parameterisasi dalam Menerapkan pengujian berparameter dan deskripsi argumen khusus dalam Mengembangkan Swift Testing Lebih Lanjut.
Fixture sengaja dibuat di dalam fungsi pengujian. Setiap pemanggilan membuat TileLayout sendiri; tidak ada yang bergantung pada skenario sebelumnya. Jika memigrasikan fixture yang sudah ada, pindahkan penyiapannya dengan sengaja, alih-alih mengharapkan hook XCTest yang diwarisi tetap berjalan. Suite Swift Testing tidak mewarisi XCTestCase; Apple memetakan penyiapan ke initializer dan pembongkaran kelas atau aktor ke deinit dalam Memigrasikan pengujian dari XCTest.
Perhitungan ini menerima jumlah ubin nonnegatif dan jumlah kolom yang benar-benar positif. Prakondisinya menetapkan kontrak tersebut; nilai tidak valid berada di luar cakupan kasus contoh ini. Jika kode aplikasi yang sebenarnya harus mengembalikan error yang dapat dipulihkan untuk input tidak valid, ubah kontrak API tersebut dan tambahkan pengujian terkait sebelum memperluas tabel ini.
Pastikan hasil terpisah dan jalankan ulang satu kasus yang gagal
Jalankan fungsi berparameter menggunakan ikon berlian di samping deklarasinya. Lalu buka Test navigator dan perluas fungsi tersebut untuk memeriksa kasus-kasusnya. Untuk menjalankan satu kasus, arahkan kursor ke ikon berlian kasus itu lalu klik kontrol putarnya. Mengklik kontrol putar pada fungsi induk akan menjalankan semua kasusnya. Apple mendokumentasikan kedua tindakan ini dalam Menjalankan pengujian dan menafsirkan hasil.
Untuk pemeriksaan pelaporan yang terkontrol, ubah sementara nilai expectedRows pada rekaman wrap dari 2 menjadi 3. Jalankan seluruh fungsi berparameter. Hasil yang diharapkan adalah lima eksekusi kasus, dengan perbandingan wrap gagal karena implementasi mengembalikan 2. Pilih kasus tersebut dan jalankan ulang sendiri, lalu pulihkan nilai yang diharapkan menjadi 2. Ini adalah perubahan data pengujian yang disengaja, bukan bukti adanya cacat implementasi.
Periksa detail Results dan Arguments pada ekspektasi yang gagal untuk membandingkan nilai hasil perhitungan dengan input skenario. Untuk proses yang menjalankan semua kasus, buka View > Navigators > Reports, pilih aksi pengujian, lalu periksa bagian Tests. Kontrol pemeriksaan ini dijelaskan dalam panduan hasil pengujian dari Apple.
Eksekusi selektif memiliki persyaratan tambahan selain label yang mudah dibaca: runner harus dapat mencocokkan setiap argumen secara deterministik. Dokumentasi Apple saat ini menerima CustomTestArgumentEncodable, tipe RawRepresentable tertentu, Encodable, atau Identifiable dengan identifier yang dapat di-encode. Rekaman Codable dalam contoh memenuhi jalur encoding. String tampilan khusus saja tidak memenuhi persyaratan tersebut. Lihat Menerapkan pengujian berparameter.
Aritmetika yang diharapkan untuk kelima rekaman diperiksa secara lokal menggunakan pembagian bilangan bulat dan sisa bagi Python. Implementasi keliru ilustratif yang hanya menggunakan pembagian dibulatkan ke bawah gagal pada one-tile dan wrap. File Swift telah diperiksa, tetapi tidak dikompilasi dalam lingkungan riset ini karena Swift tidak tersedia; proses Xcode di atas tetap menjadi langkah verifikasi yang dapat dieksekusi.
Pertahankan jumlah kasus dan siklus hidup yang dimaksud
Pemeriksaan migrasi yang berguna membandingkan tiga hal: jumlah rekaman skenario, kasus yang dieksekusi dalam proses penuh, dan apakah kasus yang dipilih dapat dijalankan sendiri. Untuk contoh ini, jumlah yang dimaksud adalah lima. Jumlah yang berbeda seharusnya mendorong pemeriksaan konstruksi argumen dan pemilihan pengujian sebelum perhitungan diubah.
Pertahankan ekspektasi yang berpasangan agar tetap bersama. Meneruskan dua koleksi terpisah ke arguments: menghasilkan produk Kartesiusnya. Lima input dan lima output yang diharapkan akan menghasilkan 25 kombinasi, bukan lima skenario yang cocok berpasangan. Gunakan koleksi terpisah bila setiap kombinasi bermakna; gunakan rekaman atau zip() untuk data yang berpasangan. Apple menjelaskan perbedaan ini dalam Menerapkan pengujian berparameter.
Jika menggunakan zip(), periksa panjang koleksi sebelum membentuk pasangan: Swift berhenti pada urutan yang lebih pendek. Jika tidak, hasil yang diharapkan berlebih dapat tidak digunakan tanpa menghasilkan kasus. Satu rekaman skenario menghindari ketidakcocokan khusus ini. Perilaku pemotongan tersebut didokumentasikan dalam referensi Swift zip(::).
Urutan eksekusi juga memengaruhi keputusan migrasi. Secara bawaan, Swift Testing menjalankan kasus secara paralel. Contoh ini memiliki argumen yang tidak dapat diubah dan fixture lokal, jadi hasilnya tidak bergantung pada urutan. Untuk fungsi berparameter yang sementara perlu dijalankan secara serial, tambahkan .serialized ke atribut @Test-nya. Menerapkan trait tersebut ke sebuah suite juga menjalankan pengujian dan kasus di dalamnya secara serial, tetapi tidak menjalankan suite lain yang tidak terkait secara serial. Lihat Menjalankan pengujian secara serial atau paralel.
Eksekusi serial tidak menciptakan keadaan baru atau menetapkan kontrak dependensi skenario. Jika suatu kasus hanya berhasil setelah kasus lain mengubah sesuatu, rancang ulang penyiapannya agar kasus itu dapat dijalankan secara independen. Jika langkah-langkahnya memang merupakan satu operasi berkelanjutan, pertahankan semuanya dalam satu pengujian dan parameterisasikan operasi lengkapnya.
Gunakan assertion Swift Testing di seluruh contoh yang dimigrasikan ini. Saat menggunakan kembali helper yang berisi assertion XCTest, periksa perilaku interoperabilitas toolchain: panduan migrasi Apple saat ini mendokumentasikan mode dan nilai bawaan yang berbeda-beda menurut toolchain dan versi tools paket. Menjaga file ini sepenuhnya menggunakan Testing menghindari dependensi tersebut. Lihat Memigrasikan pengujian dari XCTest.
Jika migrasi harus ditunda, alternatif XCTest yang didukung adalah satu metode pengujian bernama tanpa parameter untuk setiap skenario, dengan helper perhitungan dan assertion bersama jika sesuai. Apple merekomendasikan satu pengujian untuk setiap skenario dalam panduan menambahkan pengujian. Cara itu mempertahankan hasil metode yang terpisah tanpa memerlukan parameterisasi Swift Testing.
Konversi selesai ketika setiap skenario awal memiliki kasus yang sesuai dan telah dieksekusi, fixture-nya dimulai dari keadaan yang dimaksud, dan kasus yang dipilih dapat berjalan dengan sukses secara mandiri. Pertahankan input batas dan output yang diharapkan selama perubahan tersebut: pelaporan independen berguna karena memudahkan pencarian, diagnosis, dan pengulangan pemeriksaan yang sudah ada.
Sumber
- Mendefinisikan Kasus dan Metode Pengujian — Apple
- Menyiapkan dan Membongkar Keadaan dalam Pengujian Anda — Apple
- Mengembangkan Swift Testing Lebih Lanjut — Apple
- Mendapatkan Swift Testing — Proyek Swift
- Menambahkan pengujian ke proyek Xcode Anda — Apple
- Menerapkan pengujian berparameter — Apple
- Memigrasikan pengujian dari XCTest — Apple
- Menjalankan pengujian dan menafsirkan hasil — Apple
- zip(::) — Apple
- Menjalankan pengujian secara serial atau paralel — Apple