Seratus test lulus belum tentu berarti seratus persen kode teruji — bisa saja seluruh test hanya menyentuh jalur bahagia dan cabang galat tidak pernah dieksekusi. Code coverage mengukur persentase kode yang benar-benar dijalankan oleh test suite, sehingga kita tahu baris mana yang belum pernah tersentuh. Chapter ini membahas cara membaca angka coverage, cara mengumpulkannya di MATLAB, dan padanan instrumen manual yang teruji di Octave:
- Konsep coverage: baris vs cabang, dan mengapa 100% bukan jaminan.
- Mengumpulkan coverage di MATLAB lewat
runtestsdan plugin. - Target coverage yang realistis untuk proyek nyata.
- Instrumen coverage manual dengan counter cabang.
Konsep Coverage: Baris yang Tersentuh #
Coverage baris (line/statement coverage) menghitung: berapa persen pernyataan yang dieksekusi setidaknya sekali saat seluruh test berjalan. Angka ini dihitung dengan instrumentasi — setiap baris kode disisipkan penanda, lalu runner mencatat penanda mana yang terlewati. Coverage cabang (branch/decision coverage) lebih ketat: setiap keputusan if/while harus teruji untuk kedua arah, benar dan salah.
Mekanisme di balik layar: runner menjalankan suite sambil mengumpulkan jejak eksekusi, membandingkannya dengan daftar seluruh pernyataan berkas sumber, lalu membagi jumlah tercakup dengan total. Baris yang tak pernah terlewati muncul merah di laporan — sinyal bahwa ada jalur program yang belum punya test.
Mengapa 100% bukan jaminan bebas galat? Dua alasan utama:
- Coverage hanya menghitung eksekusi, bukan kebenaran — baris yang dieksekusi tanpa assert yang memeriksa hasilnya tetap dihitung “tercakup”.
- 100% cabang masih menyisakan kelas masukan — input desimal, kosong, atau
NaNmungkin tidak pernah diuji meski semua cabang tersentuh.
Coverage di MATLAB (MATLAB-ONLY) #
Dua jalur resmi untuk mengumpulkan coverage di MATLAB R2026b. Jalur termudah sejak R2023b: runtests dengan argumen ReportCoverageFor:
% Sumber: dokumentasi resmi MATLAB (MATLAB-ONLY)
[testResults, coverageResults] = runtests("TestFolder", ...
ReportCoverageFor = "sourceFolder");Panggilan tersebut menjalankan test, menghasilkan laporan HTML interaktif (berkas index.html) yang menandai bagian sumber yang dieksekusi test, sekaligus mengembalikan objek matlab.coverage.Result per berkas sumber untuk akses programatik.
Jalur kedua: plugin pada runner kustom — berguna bila kita mengendalikan format keluaran (misalnya untuk CI):
% Sumber: dokumentasi resmi MATLAB (MATLAB-ONLY)
import matlab.unittest.plugins.CodeCoveragePlugin
import matlab.unittest.plugins.codecoverage.CoverageReport
runner = testrunner("textoutput");
reportFormat = CoverageReport("coverageReport");
p = CodeCoveragePlugin.forFolder("sourceFolder", Producing = reportFormat);
runner.addPlugin(p);
results = runner.run(suite);Jenis format keluaran plugin: CoverageResult (objek hasil di memori, cocok untuk pemeriksaan programatik), CoverageReport (HTML interaktif), dan CoberturaFormat (XML standar industri yang biasa dibaca layanan CI). Metrik yang bisa dikumpulkan:
| Metrik | Arti | Ketersediaan |
|---|---|---|
"statement" | pernyataan dieksekusi | MATLAB dasar |
"decision" | tiap keputusan teruji dua arah | MATLAB Test (lisensi terpisah) |
"condition" | tiap kondisi boolean teruji dua arah | MATLAB Test |
"mcdc" | kombinator kondisi (standar avionik) | MATLAB Test |
Ringkasan programatik contoh dari dokumentasi resmi — fungsi quadraticSolver dengan empat pernyataan, seluruhnya dieksekusi oleh SolverTest:
summary = coverageSummary(result, "statement")
summary = 1×2
4 4Angka pertama adalah jumlah pernyataan yang tercakup, angka kedua total pernyataan — 4 dari 4 berarti cakupan penuh untuk berkas tersebut.
Target Coverage yang Realistis #
Angka coverage adalah indikator, bukan tujuan. Panduan praktis yang umum dipakai industri:
| Rentang | Interpretasi praktis |
|---|---|
| < 40% | banyak jalur tak teruji; prioritas menulis test |
| 60-80% | wilayah nyaman untuk proyek bisnis pada umumnya |
| > 90% | wajar untuk pustaka kritis/utilitas inti |
| 100% | biaya tinggi, nilai tambah menurun; sisanya test sulit |
Instrumen Manual: Counter per Cabang #
Tanpa MATLAB, kita meniru instrumentasi dengan counter yang diperbarui fungsi yang diuji. Berkas uji_coverage.m di bawah halaman ini menginstrumentasi fungsi klasifikasi() yang punya empat cabang. Potongan suite pertama:
% --- Suite 1: dua test, hanya menyentuh 2 dari 4 cabang ---
fprintf('== Suite 1: input [-7, 0] ==\n');
counter = zeros(1, jumlahCabang);
[label, counter] = klasifikasi(-7, counter);
fprintf('input -7 -> %s\n', label);
[label, counter] = klasifikasi(0, counter);
fprintf('input 0 -> %s\n', label);
cetakLaporan(namaCabang, counter);Sementara itu, satu cabang klasifikasi() sendiri berbentuk counter(1) = counter(1) + 1; — menambah satu pada slot milik cabang tersebut. Laporan dan persentase dihitung cetakLaporan():
tercakup = sum(counter > 0);
persen = 100 * tercakup / numel(counter);
fprintf('Coverage cabang: %d/%d = %.0f%%\n\n', ...
tercakup, numel(counter), persen);Output yang Dihasilkan (dari uji_coverage.m lengkap):
== Suite 1: input [-7, 0] ==
input -7 -> negatif
input 0 -> nol
Cabang Eksekusi
negatif 1
nol 1
positif genap 0
positif ganjil 0
Coverage cabang: 2/4 = 50%
== Suite 2: input [-7, 0, 8, 3] ==
input -7 -> negatif
input 0 -> nol
input 8 -> positif genap
input 3 -> positif ganjil
Cabang Eksekusi
negatif 1
nol 1
positif genap 1
positif ganjil 1
Coverage cabang: 4/4 = 100%
Catatan: 100% cabang bukan jaminan bebas galat;
input 2.5 (desimal) belum pernah diuji padahal lolos hitung.Mari kita bedah baris-baris kode di atas:
- Baris 3 (
counter = zeros(1, jumlahCabang)): alokasi satu counter per cabang — padanan sederhana penanda yang disisipkan instrumen coverage MATLAB ke tiap pernyataan sumber. - Baris 4 dan 6 (
[label, counter] = klasifikasi(...)): fungsi yang diuji mengembalikan counter yang sudah diperbarui; setiap cabang menambah satu pada slot miliknya sendiri. - Blok kedua (
tercakup ... fprintf): cabang dihitung tercakup bila counter-nya lebih dari nol; persentase = tercakup / total. - Suite 1 vs Suite 2: dua test hanya menyentuh 2 dari 4 cabang (50%); menambah dua test lagi menaikkan semua counter hingga 100% — persis cara kerja laporan coverage sesungguhnya, hanya dalam skala kecil.
- Catatan terakhir: meski 4/4 = 100%, kelas masukan desimal belum pernah diuji — bukti konkret bahwa angka penuh tetap menyisakan celah.
Ringkasan #
Coverage baris mengukur persentase pernyataan yang dieksekusi test; coverage cabang menuntut kedua arah tiap keputusan teruji. Di MATLAB, runtests dengan ReportCoverageFor menghasilkan laporan HTML plus objek matlab.coverage.Result (R2023b+), atau plugin CodeCoveragePlugin dengan format CoverageResult/CoverageReport/CoberturaFormat untuk runner kustom. Target pragmatis 60-80% dan prioritas pada cabang galat yang kosong. Instrumen manual dengan counter per cabang — seperti uji_coverage.m — menunjukkan mekanisme di balik angka tersebut dan berjalan penuh di Octave.