Debugger menemukan bug setelah gejala muncul; assert menyalakan alarm tepat saat asumsi dilanggar, sebelum galat merambat jauh dari sumbernya. Assertion adalah pernyataan “kondisi ini pasti benar pada titik ini” — kalau ternyata salah, program layak berhenti seketika karena asumsi fondasinya sudah runtuh. Chapter ini membahas bentuk assert(), perannya sebagai dokumentasi asumsi (precondition, postcondition, invariant), dan batas tegasnya dibanding error() untuk validasi input pengguna.
Bentuk dan Perilaku assert() #
assert(kondisi) mengevaluasi kondisi; bila bernilai true, program berjalan seolah perintah itu tidak ada. Bila false, assert melempar galat bawaan dan eksekusi berhenti di baris itu — mekanisme yang sama dengan error(), hanya satu langkah lebih ringkas. Bentuk lengkapnya membawa pesan ber-format specifier persis seperti sprintf:
assert(2 + 2 == 4, 'aritmetika dasar tidak konsisten');
fprintf('assert lulus, eksekusi berlanjut ke baris berikutnya\n');
assert(1 > 2, 'kondisi %d > %d ternyata salah', 1, 2); % gagalOutput yang Dihasilkan (kasus 1 dari contoh.m):
== Kasus 1: assertion lulus ==
assert lulus, eksekusi berlanjut ke baris berikutnyaMari kita bedah baris-baris kode di atas:
- Baris 1 (
assert(2 + 2 == 4, ...)): kondisi bernilai true — assertion berlalu tanpa jejak, danfprintfdi baris berikutnya membuktikan alur tidak terganggu. - Baris 4 (
assert(1 > 2, 'kondisi %d > %d ...', 1, 2)): kondisi false —assertmemformat pesan dengan argumen 1 dan 2 (%d) lalu melempar galat. Baris kedua output berasal dari blokcatchyang menangkapnya di berkascontoh.m— galatassertadalahMExceptionbiasa sehingga bisa ditangkap persis seperti galaterror().
Assertions sebagai Dokumentasi Asumsi #
Kekuatan assertion yang jarang disadari: ia adalah dokumentasi yang dieksekusi. Komentar bisa kedaluwarsa diam-diam; assertion yang berhenti berkata “komentar ini sudah bohong”. Tiga posisi klasiknya:
| Jenis asumsi | Dipasang di | Pertanyaan yang dikunci |
|---|---|---|
| Precondition | awal fungsi, sebelum komputasi | “masukan pemanggil selalu seperti ini?” |
| Postcondition | akhir fungsi, sebelum return | “hasil keluaran selalu memenuhi sifat ini?” |
| Invariant | badan loop, setiap iterasi | “sifat apa yang tak boleh berubah antar iterasi?” |
Berkas sumber chapter ini memuat hitung_diskon() — versi fungsi jumlah_diskon() yang sudah diperbaiki, dengan precondition di bagian atasnya:
function total = hitung_diskon(harga, persenDiskon)
% HITUNG_DISKON menjumlahkan harga setelah diskon (versi diperbaiki).
% total = hitung_diskon(harga, persenDiskon)
% Assertions di awal berfungsi sebagai dokumentasi asumsi fungsi.
assert(isnumeric(harga) && all(isfinite(harga(:))), ...
'harga harus berupa array angka finite');
assert(isscalar(persenDiskon) && persenDiskon >= 0 && ...
persenDiskon <= 100, ...
'persenDiskon harus skalar dalam rentang 0..100');
total = sum(harga) * (1 - persenDiskon / 100);
endMari kita bedah baris-baris kode di atas:
- Baris 6-7 (
assert(isnumeric(harga) ...)): precondition pertama —hargaharus array angka tanpa elemenNaN/Inf;harga(:)meratakan array agarall()memeriksa setiap elemen berapapun dimensinya. - Baris 8-10 (
assert(isscalar(persenDiskon) ...)): precondition kedua —persenDiskonskalar dalam rentang wajar; tiga syarat digabung operator&&jadi satu kondisi. - Baris 12 (
total = sum(harga) ...): baris komputasi dapat ditulis sederhana karena asumsi sudah dikunci — pembaca tahu persis kontrak masukan fungsi ini tanpa membaca implementasinya.
Contoh invariant loop ada di contoh.m: setelah sort(), elemen ke-k wajib tidak melebihi elemen ke-k+1 — assertion di badan loop memeriksa sifat itu setiap iterasi.
assert atau error? #
Keduanya melempar MException, tetapi kegunaannya berbeda arah. assert menyatakan bug programmer: kondisi yang menurut logika program “tidak seharusnya mungkin” terjadi — kalau terjadi, kodenya yang salah. error() menyatakan input pengguna yang tidak sah: kondisi yang wajar terjadi dari luar dan harus ditolak dengan pesan ramah. Beda arah ini menentukan gaya penanganan:
| Aspek | assert | error() |
|---|---|---|
| Untuk | bug internal, asumsi programmer | validasi masukan pengguna |
| Terpicu berarti | kode kita salah, perlu perbaikan | pengguna salah input, perlu pesan jelas |
| Pesan ditujukan bagi | programmer (teknis) | pengguna (aman dibaca) |
| Identifier kustom | tidak — identifier kosong | ya — error('proyek:kejadian', ...) |
Praktik umum: fungsi publik yang menerima masukan dari pengguna memvalidasi dengan error(), sementara bagian internal — helper privat, inisialisasi, invariant algoritma — dipagari assert.
Assert sebagai Fondasi Uji Otomatis #
Satu assertion memberi satu alarm; rangkaian assertion yang dijalankan ulang setiap ada perubahan kode itulah unit test — dan assert adalah bahan bakarnya. Pola minimalnya: panggil fungsi dengan masukan yang diketahui, bandingkan hasil dengan ekspektasi lewat assert(isequal(hasil, ekspektasi), 'pesan'). Kegagalan assertion otomatis berarti uji gagal. contoh.m menutup dengan pola ini pada hitung_diskon(): masukan valid [100 200 300] dan 10 menghasilkan 540 yang diadu lewat assertion, lalu masukan tidak valid 150 untuk persenDiskon ditolak precondition — dua kejadian yang di chapter berikutnya dikembangkan menjadi suite uji_matematikaDasar.m.
Output yang Dihasilkan (kasus 2-4 dan bonus dari contoh.m):
== Kasus 2: hasil diadu dengan ekspektasi ==
hitung_diskon([100 200 300], 10) = 540
== Kasus 3: assertion fungsi gagal ==
assert gagal : persenDiskon harus skalar dalam rentang 0..100
== Kasus 4: invariant loop ==
semua invariant loop terpenuhi
== Bonus: assert dengan pesan berformat ==
pesan terformat: kondisi 1 > 2 ternyata salahRingkasan #
assert(kondisi, 'pesan') mengevaluasi kondisi dan melempar MException bila false — alarm dini yang berbunyi tepat di titik asumsi runtuh. Pasang sebagai precondition di awal fungsi, postcondition sebelum keluaran, dan invariant di badan loop; assertion menjadi dokumentasi asumsi yang dieksekusi sehingga tidak bisa kedaluwarsa diam-diam. Arahkan assert untuk bug internal programmer dan error() untuk masukan pengguna; ingat bahwa MATLAB tidak menyediakan flag mematikan assertion di produksi. Fondasi ini kita bangun menjadi kerangka pengujian penuh di chapter Unit Testing.