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:

matlab
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);   % gagal

Output yang Dihasilkan (kasus 1 dari contoh.m):

text
== Kasus 1: assertion lulus ==
assert lulus, eksekusi berlanjut ke baris berikutnya

Mari kita bedah baris-baris kode di atas:

  1. Baris 1 (assert(2 + 2 == 4, ...)): kondisi bernilai true — assertion berlalu tanpa jejak, dan fprintf di baris berikutnya membuktikan alur tidak terganggu.
  2. Baris 4 (assert(1 > 2, 'kondisi %d > %d ...', 1, 2)): kondisi false — assert memformat pesan dengan argumen 1 dan 2 (%d) lalu melempar galat. Baris kedua output berasal dari blok catch yang menangkapnya di berkas contoh.m — galat assert adalah MException biasa sehingga bisa ditangkap persis seperti galat error().

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 asumsiDipasang diPertanyaan yang dikunci
Preconditionawal fungsi, sebelum komputasi“masukan pemanggil selalu seperti ini?”
Postconditionakhir fungsi, sebelum return“hasil keluaran selalu memenuhi sifat ini?”
Invariantbadan 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:

matlab
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);
end

Mari kita bedah baris-baris kode di atas:

  1. Baris 6-7 (assert(isnumeric(harga) ...)): precondition pertama — harga harus array angka tanpa elemen NaN/Inf; harga(:) meratakan array agar all() memeriksa setiap elemen berapapun dimensinya.
  2. Baris 8-10 (assert(isscalar(persenDiskon) ...)): precondition kedua — persenDiskon skalar dalam rentang wajar; tiga syarat digabung operator && jadi satu kondisi.
  3. 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:

Aspekasserterror()
Untukbug internal, asumsi programmervalidasi masukan pengguna
Terpicu berartikode kita salah, perlu perbaikanpengguna salah input, perlu pesan jelas
Pesan ditujukan bagiprogrammer (teknis)pengguna (aman dibaca)
Identifier kustomtidak — identifier kosongya — 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):

text
== 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 salah

Ringkasan #

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.