Program yang tidak diuji hanyalah program yang kita harapkan benar. Bagian 1 sampai 3 sesekali menjalankan satu fungsi, tetapi harapan bukan bukti. Pada bagian ini kita merangkai tiga berkas uji — unit untuk operasi, unit untuk validasi, dan end-to-end untuk program utuh — lalu menjalankannya sampai semua kasus lulus dan kegagalan apa pun terdeteksi otomatis.
Yang kita bangun pada bagian ini:
- struktur
tests/beserta pola mengaksessrc/dari berkas uji, - pola tabel kasus berbasis
assertdan anonymous function, - uji kasus galat — error yang diharapkan justru harus terjadi,
- uji end-to-end mode demo beserta pemeriksaan transkripnya,
- checklist kualitas dan ide pengembangan lanjutan.
Struktur Berkas Uji #
Tiga berkas uji membagi tanggung jawab menurut cakupan, dari satu fungsi sampai program utuh:
| Berkas | Cakupan | Kasus |
|---|---|---|
uji_operasi.m | fungsi operasi + validasi dimensi | 13 |
uji_validasi.m | parserMatriks + seluruh aturan tolakan | 14 |
uji_end_to_end.m | program utuh lewat mode demo | 4 |
Setiap berkas mandiri dan boleh dijalankan sendiri. Kuncinya ada di tiga baris pembuka tiap berkas:
% Pastikan folder src/ dapat diakses dari lokasi berkas ini,
% entah dijalankan dari tests/ maupun dari lokasi lain.
folderIni = fileparts(mfilename('fullpath'));
addpath(fullfile(folderIni, '..', 'src'));Mari kita bedah baris-baris kode di atas:
- Baris 2 (
folderIni = fileparts(mfilename('fullpath'));):mfilename('fullpath')mengembalikan lokasi berkas yang sedang berjalan — bukan folder aktif pengguna. Test menjadi tidak peduli dari mana ia dijalankan. - Baris 3 (
addpath(fullfile(folderIni, '..', 'src'));):fullfilemerangkai path lintas sistem operasi;'..'naik satu tingkat daritests/kesrc/. Dengan path terpasang, test bisa memanggilkalkulatordan kawan-kawannya langsung.
Pola Uji: Tabel Kasus dengan assert #
Tanpa framework, kita tetap bisa menulis test yang rapi dengan tiga bahan: tabel kasus, assert, dan try/catch. Tabel kasus sudah kita lihat pada Bagian 2 dan 3 — tiap baris memuat nama kasus dan anonymous function yang memanggil assert. Mesin pengujinya satu loop:
for k = 1:size(kasus, 1)
try
kasus{k, 2}();
nLulus = nLulus + 1;
fprintf('LULUS: %s\n', kasus{k, 1});
catch
nGagal = nGagal + 1;
fprintf('GAGAL: %s\n', kasus{k, 1});
end
endMari kita bedah baris-baris kode di atas:
- Baris 3 (
kasus{k, 2}();): kurung kurawal mengambil elemen cell (sebuah function handle), lalu()mengeksekusinya. Semua kasus berjalan lewat baris yang sama — menambah kasus berarti menambah satu baris tabel, bukan menyalin loop. - Baris 6 (
catch):assertyang gagal melempar error;catchtanpa variabel menangkapnya dan hanya mencatat GAGAL. Satu kasus gagal tidak menghentikan kasus berikutnya — kita melihat seluruh laporan dulu. - Penghitung
nLulus/nGagal: di akhir berkas, ringkasan dicetak danerror()sengaja dilempar bila ada kegagalan — kode keluar proses menjadi tak-nol sehingga runner otomatis (CI, skrip) mendeteksinya tanpa membaca layar.
Menguji Kasus Galat #
Kasus galat dibalik logikanya: panggilan harus melempar error, dan pesannya harus memuat potongan teks yang diharapkan. Tabelnya punya tiga kolom — nama, panggilan, dan fragmen pesan — sementara loop pengujinya menangkap galat lalu memeriksa isinya:
for k = 1:size(galat, 1)
lulus = false;
try
galat{k, 2}(); % wajib melempar galat
catch err
lulus = ~isempty(strfind(err.message, galat{k, 3}));
end
if lulus
nLulus = nLulus + 1;
fprintf('LULUS: %s\n', galat{k, 1});
else
nGagal = nGagal + 1;
fprintf('GAGAL: %s\n', galat{k, 1});
end
endPemeriksaannya bekerja bertingkat: bila panggilan tidak melempar galat, lulus tetap false (baris 2) — kasus gagal karena error yang dijanjikan tidak ada. Bila galat terjadi namun pesannya tidak memuat fragmen yang diharapkan, strfind menghasilkan kosong dan kasus juga gagal. Dengan memeriksa pesan, test melindungi kontrak yang paling terlihat pengguna: teks galat yang informatif dari Bagian 3 tidak boleh berubah tanpa disadari.
Uji End-to-End Mode Demo #
Uji unit membuktikan tiap fungsi benar; uji end-to-end membuktikan rakitannya berjalan. Di sinilah mode demo dari Bagian 1 terbayar: kalkulator('demo') menjalankan delapan skenario tanpa keyboard, sehingga bisa dieksekusi dari test. evalc menangkap seluruh keluarannya sebagai teks:
% ---- kasus 1: seluruh skenario demo berjalan tanpa galat ----
% evalc menjalankan kalkulator('demo') dan menangkap seluruh
% keluarannya sebagai teks, sehingga program tetap diuji penuh
% tanpa mencetak puluhan baris sesi ke layar.
transkrip = '';
ok1 = false;
try
transkrip = evalc('kalkulator(''demo'');');
ok1 = true;
catch err
fprintf(' mode demo melempar galat: %s\n', err.message);
endBerkas ini juga menguji hasil antara — matriks dari teks skenario diperiksa hasil tambah dan kalinya — lalu memeriksa transkrip memuat hasil kunci tiap skenario:
ok4 = ~isempty(strfind(transkrip, 'Hasil:')) && ...
~isempty(strfind(transkrip, 'Determinan = 10')) && ...
~isempty(strfind(transkrip, 'Ukuran tidak kompatibel: 2x2 vs 3x2')) && ...
~isempty(strfind(transkrip, 'Pilihan tidak dikenal')) && ...
~isempty(strfind(transkrip, 'Terima kasih. Program selesai.'));Lima fragmen itu sengaja dipilih: Hasil: membuktikan operasi mencetak hasil, Determinan = 10 membuktikan hitungan skenario kelima benar, Ukuran tidak kompatibel: 2x2 vs 3x2 membuktikan galat dimensi tertangkap (program tidak berhenti), Pilihan tidak dikenal membuktikan cabang otherwise hidup, dan Terima kasih. Program selesai. membuktikan loop berakhir dengan rapi. Menjalankan berkas dari folder tests/ memberi hasil:
Output yang Dihasilkan:
== uji_end_to_end.m ==
Matriks A (contoh: 1 2; 3 4): 1 2; 3 4
LULUS: mode demo berjalan penuh tanpa galat
LULUS: bacaMatriks mode demo mengembalikan matriks
LULUS: hasil antara konsisten dengan data skenario
LULUS: transkrip memuat hasil kunci tiap skenario
Ringkasan: 4 lulus, 0 gagal (total 4)Baris kedua adalah gema bacaMatriks mode demo — bukan kebocoran, melainkan bukti jalur baca ikut teruji. Peta cakupan ketiga berkas tersusun berlapis:
Hasil Uji Menyeluruh #
Ketiga berkas dijalankan utuh lewat runner Octave 10.3 dalam mode batch. Ringkasan akhirnya:
| Berkas | Cakupan | Kasus | Hasil |
|---|---|---|---|
uji_operasi.m | operasi + validasi dimensi | 13 | 13 lulus, 0 gagal |
uji_validasi.m | parser + aturan tolakan | 14 | 14 lulus, 0 gagal |
uji_end_to_end.m | program utuh mode demo | 4 | 4 lulus, 0 gagal |
Total 31 kasus, semuanya lulus, dan ketiganya berakhir dengan kode keluar 0 karena berkas uji memang dilempar error hanya bila ada kegagalan. Dari 31 kasus itu, 12 di antaranya adalah kasus galat — program diuji justru pada kondisi ketika semuanya salah.
Checklist Kualitas Program #
Sebelum menutup proyek, mari audit hasil kerja kita terhadap janji-janji di Bagian 1:
| Aspek kualitas | Bukti |
|---|---|
| Input pengguna tidak dieksekusi | parser tanpa eval/str2num; kasus token terlarang lulus |
| Dimensi diperiksa sebelum menghitung | validasiDimensi dipanggil semua operasi biner; 3 kasus galat dimensi |
| Determinan hanya untuk matriks persegi | validasiPersegi; kasus determinan 2x3 ditolak |
| Program tahan galat | skenario demo ke-6: galat tercetak, menu kembali |
| Pilihan tak dikenal tidak menghentikan program | skenario 9 jatuh ke otherwise |
| Ukuran dibatasi 10x10 | kasus 11 baris dan 11 kolom ditolak |
| Nilai meluap ditolak | kasus 1e999 ditolak dengan pesan rentang |
| Keluaran rapi dan deterministik | tampilkanMatriks rata kanan; format %g tuntas |
Delapan dari delapan — checklist terpenuhi karena setiap barisnya punya kasus uji yang menyandang bukti, bukan keyakinan.
Ide Pengembangan Lanjutan #
Struktur yang ada — menu, dispatch, parser, dan test — siap menampung fitur baru. Kandidat berikut urut dari yang paling mudah:
- invers matriks — cabang menu baru
inversMatriks.m; validasi: matriks persegi dandet(A) ~= 0, - trace, rank, dan nilai eigen — semua satu
validasiPersegiplus satu panggilan bawaantrace,rank, ataueig, - matriks siap pakai — perintah
identitas ndannol m nyang mengisi matriks lewateye/zeros, - riwayat hasil — simpan hasil terakhir, lalu teks
hasilpada prompt dipakai sebagai matriks baru, - presisi tampilan — opsi menu untuk mengganti
%gmenjadi%.3f, - baca dari file —
bacaMatriksmenambang jalur: darifopen+fgetlper baris, hasilnya tetap melewatiparserMatriks.
Setiap kandidat menuntut hal yang sama: satu fungsi baru di src/, satu cabang switch di kalkulator.m, satu baris skenario demo, dan beberapa baris kasus uji — pola kerja yang sudah terbukti.
Proyek kalkulator matriks tuntas: kerangka dari Bagian 1, mesin hitung dari Bagian 2, gerbang validasi dari Bagian 3, dan bukti dari Bagian 4 membentuk satu program interaktif yang tahan salah ketik dan teruji menyeluruh. Pola yang kita pakai — loop menu, dispatch switch, parser tanpa eval, validasi fail-fast, dan uji berlapis — adalah cetak biru yang bisa kamu bawa ke program MATLAB berikutnya, sekecil apa pun mulainya.