Hari 29: Testing, Debugging & Best Practices
65 min
Last updated 26 Mar 2026
Mengapa Testing?
Testing memastikan kode bekerja sesuai harapan, mencegah bug saat ada perubahan, dan membuat kode lebih mudah di-refactor dengan percaya diri.
unittest — Testing Bawaan Python
import unittest
def bagi(a, b):
if b == 0:
raise ZeroDivisionError("Tidak bisa bagi nol")
return a / b
def is_prima(n):
if n < 2: return False
for i in range(2, int(n**0.5)+1):
if n % i == 0: return False
return True
class TestMatematika(unittest.TestCase):
def test_bagi_normal(self):
self.assertEqual(bagi(10, 2), 5.0)
def test_bagi_desimal(self):
self.assertAlmostEqual(bagi(1, 3), 0.333, places=2)
def test_bagi_nol_raises(self):
with self.assertRaises(ZeroDivisionError):
bagi(10, 0)
def test_is_prima(self):
prima = [2, 3, 5, 7, 11, 13, 17, 19, 23]
bukan = [0, 1, 4, 6, 8, 9, 10, 15]
for n in prima:
self.assertTrue(is_prima(n))
for n in bukan:
self.assertFalse(is_prima(n))
if __name__ == "__main__":
unittest.main(verbosity=2)
pytest — Testing Modern (pip install pytest)
import pytest
def test_bagi_normal():
assert bagi(10, 2) == 5.0
def test_bagi_nol():
with pytest.raises(ZeroDivisionError):
bagi(10, 0)
@pytest.mark.parametrize("n,expected", [
(2, True), (3, True), (4, False), (17, True), (100, False),
])
def test_is_prima(n, expected):
assert is_prima(n) == expected
# Jalankan: pytest test_file.py -v
Python Best Practices (PEP 8)
# Penamaan
MAX_NILAI = 100 # UPPER_CASE untuk konstanta
nama_user = "Budi" # snake_case untuk variabel & fungsi
class SistemNilai: pass # PascalCase untuk class
# Docstring
def hitung_rata(data: list) -> float:
"""Hitung rata-rata dari list angka.
Args:
data: list of int/float
Returns:
float: rata-rata nilai, 0.0 jika list kosong
"""
return sum(data) / len(data) if data else 0.0
# Hindari magic number
PASSING_GRADE = 70 # beri nama yang bermakna
if nilai >= PASSING_GRADE:
print("Lulus")
Type Hints (Python 3.5+)
from typing import List, Dict, Optional, Tuple
def sapa(nama: str, salam: str = "Halo") -> str:
return f"{salam}, {nama}!"
def statistik(data: List[float]) -> Dict[str, float]:
return {"min": min(data), "max": max(data), "avg": sum(data)/len(data)}
def cari_user(user_id: int) -> Optional[Dict]:
... # None jika tidak ditemukan
# Jalankan type checking: pip install mypy && mypy script.py
Debugging
# breakpoint() — Python 3.7+
def cari_bug(data):
hasil = 0
for i, n in enumerate(data):
breakpoint() # berhenti di sini, bisa inspect variabel
hasil += n * i
return hasil
# Perintah pdb: n(ext), s(tep), c(ontinue), p expr, l(ist), q(uit)
# Cara sederhana: print debugging
def proses(data):
print(f"[DEBUG] Input: {data}") # tambah sementara
hasil = sorted(data)
print(f"[DEBUG] Sorted: {hasil}")
return hasilAssignment
Buat test lengkap untuk class RekeningBank menggunakan unittest. Uji: saldo awal, deposit normal, deposit negatif (ValueError), tarik normal, tarik melebihi saldo (ValueError), dan konstruktor dengan saldo negatif (ValueError).
Expected output:
test_deposit_negatif_raises ... ok
test_deposit_nol_raises ... ok
test_deposit_normal ... ok
test_konstruktor_saldo_negatif ... ok
test_saldo_awal ... ok
test_tarik_melebihi_saldo_raises ... ok
test_tarik_normal ... ok
------
Ran 7 tests in 0.001s
OK
PY
main.py
Solution
Output