Kode yang tidak diuji adalah tebakan yang berpura-pura menjadi program. Sepanjang Course kita membangun kebiasaan mengunci setiap perilaku dengan assertion, menata berkas uji di folder tests/, dan menjalankan seluruh suite sebelum menyatakan kode selesai. Chapter ini memadatkan praktik tersebut menjadi satu halaman rujukan: peta level pengujian, konvensi folder, pola suite manual portabel, rekap matlab.unittest, checklist sebelum rilis, dan gagasan TDD dalam bentuk paling ringkas.
Tiga Level Pengujian #
Uji yang baik bertingkat seperti corong: cepat dan granular di dasar, realistis di ujung. Tabel berikut memetakan ketiga level yang kita pakai beserta perkakasnya:
| Level | Scope | Perkakas | Durasi ideal |
|---|---|---|---|
| unit | satu fungsi terisolasi: masukan tetap → keluaran dibanding assertion | assert, matlab.unittest | milidetik per uji |
| integration | beberapa fungsi bekerja bersama: baca CSV → hitung → tulis laporan | suite berurutan, berkas sementara | detik |
| end-to-end | skrip utuh dari data nyata sampai output akhir | contoh.m proyek, exit code | detik–menit |
Prinsip pembagiannya sederhana: galat di level unit menunjuk satu fungsi; galat di level integration menunjuk sambungan antar-fungsi; galat end-to-end menunjuk asumsi dunia nyata. Semakin rendah galat tertangkap, semakin murah perbaikannya.
Struktur Folder tests/ #
Konvensi Course menempatkan seluruh berkas uji di folder tests/ dengan prefiks uji_ — uji_matematikaDasar.m, uji_konversi.m, bukan uji1.m. Tiga aturan menempel pada konvensi itu. Pertama, nama uji harus unik di seluruh proyek karena dua class bernama sama akan bertabrakan saat runner memuat keduanya. Kedua, satu berkas uji menguji satu subjek agar kegagalan mudah dilacak. Ketiga, suite harus bisa dijalankan satu perintah: runtests('tests') di MATLAB, atau pemanggilan berkas satu per satu di Octave — vonis akhir dibaca dari exit code (nol = lulus), sehingga alat CI pun cukup memeriksa satu angka.
Pola Suite Manual Portabel #
Ketika matlab.unittest tidak tersedia (misalnya di Octave), suite dengan kemampuan yang sama bisa dibangun dari assert, try-catch, dan function handle. Fungsi periksa.m menjadi runner satu-uji:
function ok = periksa(namaUji, fungsiUji)
% PERIKSA menjalankan satu uji manual berbasis assert.
ok = false;
try
assert(fungsiUji(), 'kondisi uji tidak terpenuhi');
fprintf('LULUS %s\n', namaUji);
ok = true;
catch err
fprintf('GAGAL %s\n', namaUji);
fprintf(' %s\n', err.message);
end
endSatu suite (uji_contoh.m) mendaftarkan pasangan {deskripsi, handle} lalu mengiterasinya:
lulus = 0; gagal = 0;
daftarUji = { ...
'sum() menjumlahkan seluruh elemen', @() isequal(sum([1 2 3 4]), 10); ...
'mean() menghitung rata-rata', @() isequal(mean([2 4 6]), 4); ...
'std() sample memakai n-1', @() abs(std([4 5 6 7 8]) - 1.5811) < 1e-4};
for i = 1:size(daftarUji, 1)
if periksa(daftarUji{i, 1}, daftarUji{i, 2})
lulus = lulus + 1;
else
gagal = gagal + 1;
end
end
fprintf('Ringkasan: %d lulus, %d gagal\n', lulus, gagal);
if gagal > 0
error('uji:adaGagal', '%d uji gagal', gagal);
endOutput yang Dihasilkan:
LULUS sum() menjumlahkan seluruh elemen
LULUS mean() menghitung rata-rata
LULUS std() sample memakai n-1
Ringkasan: 3 lulus, 0 gagalDua keputusan desain pada pola ini layak diingat. Anonymous function @() ... menunda evaluasi ekspresi sehingga galat runtime di dalam uji tetap tertangkap periksa, bukan menghentikan suite. Perbandingan angka pecah selalu memakai toleransi (abs(a - b) < 1e-4), bukan isequal telanjang — float yang benar secara matematis boleh berbeda satu bit.
matlab.unittest Sekilas #
Kerangka resmi MATLAB memakai class turunan matlab.unittest.TestCase; tiap metode ber-atribut (Test) adalah satu uji, dan metode kualifikasi verify* mencatat kegagalan tanpa menghentikan metode:
| Metode | Memeriksa | Contoh |
|---|---|---|
verifyEqual | kesetaraan (dengan toleransi presisi) | testCase.verifyEqual(sum([1 2 3]), 6) |
verifyTrue / verifyFalse | kondisi logical | testCase.verifyTrue(issorted(v)) |
verifyGreaterThan / verifyLessThan | urutan | testCase.verifyLessThan(sqrt(2), 1.42) |
verifyEmpty / verifyNumElements | ukuran | testCase.verifyNumElements(M, 12) |
verifyError | fungsi melempar galat yang diharapkan | testCase.verifyError(@() f(0), 'MATLAB:badsubscript') |
Jalankan dengan runtests('NamaClassTest') atau runtests('tests'). Blok methods (TestMethodSetup)/(TestMethodTeardown) menyiapkan dan membersihkan fixture per uji; seluruh kerangka ini MATLAB-ONLY (tidak berjalan di Octave) sehingga Course selalu menyediakan padanan manual di atas.
Checklist Sebelum Rilis #
Sepuluh pemeriksaan terakhir sebelum kode disebut selesai — semuanya pernah menyelamatkan proyek Course:
- Seluruh suite
uji_*.mlulus; exit code nol. - Output deterministik: dua kali eksekusi menghasilkan teks byte yang sama.
- Edge case teruji: elemen tunggal, indeks terakhir, nol dan nilai negatif.
- Perilaku terhadap
NaNdan array kosong[]sudah eksplisit (mask~isnan, cekisempty). - Validasi input di fungsi publik:
nargin,isnumeric,error('ns:kode', ...). - Path berkas relatif terhadap lokasi skrip (
fileparts(mfilename('fullpath'))), bukan current folder. - Berkas sementara dibersihkan:
delete,rmdir, atau fixturecreateTemporaryFolder. - Tiap fungsi publik punya baris bantuan H1 (
%NAMAFUNGSI ringkasan) yang terbacahelp. - Versi minimum tercatat di README (fitur yang dipakai, mis.
arguments= R2019b+). - Contoh acak memakai seed tetap (
rng(42)) dan hasilnya stabil.
TDD dalam Satu Paragraf #
Test-driven development membalik urutan kerja: tulis uji yang gagal lebih dulu (merah), tulis kode termudah yang meluluskannya (hijau), lalu rapikan tanpa mengubah perilaku (refaktor). Manfaat utamanya bukan jumlah uji, melainkan desain: menulis uji lebih dulu memaksa fungsi dilihat dari sudut pemanggilnya — masukan dan keluaran harus jelas sebelum implementasi ada. Pola ini pas diterapkan per fungsi; jangan menunggu seluruh modul jadi untuk mulai menguji.
Ringkasan #
Pengujian Course bertingkat dari unit hingga end-to-end, ditata di folder tests/ dengan konvensi uji_*.m dan vonis exit code. Pola manual portabel (periksa + daftarUji + toleransi) menghadirkan suite yang identik di MATLAB dan Octave; matlab.unittest menambah metode verify*, fixture, dan runner resmi di MATLAB. Sepuluh poin checklist rilis menjaga determinisme, kebersihan berkas, dan dokumentasi; TDD menyediakan urutan kerja yang membuat semua itu terbangun sejak awal.