Setelah menulis test berminggu-minggu, pertanyaan yang pasti muncul: “apakah test saya sudah cukup?”. Kita tidak bisa menjawab dengan membaca semua test satu per satu — proyek nyata punya ratusan fungsi. Code coverage memberi angka awal: persentase baris kode produksi yang pernah dieksekusi saat test berjalan. Angka ini bukan ukuran kebenaran, tetapi kompas yang menunjukkan wilayah kode yang belum pernah tersentuh test sama sekali. Pada Chapter ini kita menjalankan pengukuran dengan pytest-cov dan coverage, lalu membedah cara membaca dan menafsirkan hasilnya.

Apa yang Diukur (dan yang Tidak) #

Coverage mengukurCoverage tidak mengukur
Baris yang pernah dieksekusi saat test berjalanapakah assertion pada baris itu benar
Fungsi yang tak pernah dipanggil testapakah test memeriksa perilaku yang tepat
Cabang if yang tak pernah dilaluikebenaran logika bisnis secara keseluruhan

Sebuah baris yang dieksekusi tanpa assertion apa pun tetap dihitung tercakup. Itulah sebabnya angka coverage yang tinggi bukan jaminan bebas bug — ia hanya menjamin tidak ada wilayah yang sepenuhnya gelap.

Mengukur dengan pytest-cov #

Plugin pytest-cov menyematkan pengukuran langsung ke perintah pytest. Kita uji kalkulator.py dengan test yang sengaja hanya menyentuh tambah() dan jalur normal bagi():

python
from kalkulator import tambah, bagi

def test_tambah_dua_angka():
    assert tambah(2, 3) == 5

def test_bagi_dua_angka():
    assert bagi(10, 4) == 2.5

Jalankan dengan flag --cov:

bash
python3 -m pytest -q --cov=kalkulator --cov-report=term-missing

Output yang Dihasilkan:

text
..                                                                       [100%]
================================ tests coverage ================================
_______________ coverage: platform linux, python 3.12.15-final-0 _______________

Name            Stmts   Miss  Cover   Missing
---------------------------------------------
kalkulator.py      13      4    69%   9-10, 18, 23
---------------------------------------------
TOTAL              13      4    69%
2 passed in 0.07s

Cara membaca tabelnya:

  1. Kolom Stmts: jumlah statement yang bisa dieksekusi pada kalkulator.py.
  2. Kolom Miss: empat baris tidak pernah dijalankan test.
  3. Kolom Missing: lokasi persisnya — baris 9-10 (constructor PembagianNolError), baris 18 (isi kurang()), dan baris 23 (raise di dalam bagi()). Jalur error pembagian nol yang kita uji pada Chapter Testing Exceptions memang tidak diuji di file ini.

Alternatif: coverage sebagai CLI #

Bila proyek belum memasang plugin pytest, tool coverage bisa dipakai berdiri sendiri:

bash
coverage run -m pytest -q

Output yang Dihasilkan:

text
..                                                                       [100%]
2 passed in 0.01s

Data terkumpul di berkas .coverage; laporan dibuka setelahnya:

bash
coverage report -m

Output yang Dihasilkan:

text
Name               Stmts   Miss  Cover   Missing
------------------------------------------------
kalkulator.py         13      4    69%   9-10, 18, 23
test_sebagian.py       5      0   100%
------------------------------------------------
TOTAL                 18      4    78%

Perhatikan bahwa coverage report juga menghitung file test sendiri — angka total jadi campuran kode produksi dan test. Perintah --cov=kalkulator pada pytest-cov lebih tepat menyasar module produksi; gunakan --cov=. untuk mengukur seluruh proyek bila memang itu tujuannya.

Mitos 100 Persen #

Mengejar 100% coverage terasa memuaskan, tetapi dua bahaya mengintai:

  • Assertion kosong. Coverage naik hanya karena baris dieksekusi, sehingga tim tertekan menambah test yang memanggil fungsi tanpa memeriksa hasil. Angka mengkilap, verifikasi tipis.
  • Test rapuh untuk kode mati. Beberapa baris (fallback darurat, guard lama) sulit diuji karena butuh kondisi ekstrem. Memaksakan 100% kerap menghasilkan test yang rumit demi baris yang tidak penting.

Panduan yang lebih sehat untuk menafsirkan coverage:

  1. Gunakan coverage untuk menemukan wilayah gelap — kode besar yang belum tersentuh test sama sekali.
  2. Prioritaskan wilayah berisiko tinggi: logika bisnis inti dan jalur error, bukan getter/setter.
  3. Tetapkan target menurut konteks (misalnya 80–90% untuk library publik), bukan angka mutlak untuk semua proyek.

Coverage menjawab “apa yang terlewat”. Kualitas kode itu sendiri — kebiasaan penulisan yang rapi dan konsisten — dijaga oleh linter dan formatter pada Chapter Linting dan Formatting.