- EN
- ID
Panduan ini untuk siapa
- Pembelajar yang menulis script multi-function dan aplikasi kecil
- Developer yang ingin rasa percaya diri sebelum refactor atau rilis
- Tim yang membutuhkan verifikasi berulang di lingkungan lokal dan CI
Apa yang akan Anda pelajari
- Perbedaan
unittest,doctest, danpytest - Cara menulis test yang mudah dibaca dengan assertions dan fixtures
- Cara menjalankan test lintas environment dengan
tox - Cara mengukur test coverage dengan
coverage.py - Mindset inti TDD untuk development yang bertahap dan andal
Mengapa topik ini penting
Testing melindungi kode Anda dari regresi dan memberi kepercayaan diri untuk memperbaiki desain dari waktu ke waktu. Tanpa test, bahkan edit kecil bisa memunculkan bug diam-diam yang sulit dideteksi manual.
Di Python, Anda bisa mulai sederhana dan meningkatkan secara bertahap. Beberapa test yang tepat sering menangkap kegagalan paling mahal lebih awal dan memudahkan kolaborasi.
Konsep inti
Jenis test dan framework
unittest: bawaan dan terstrukturpytest: populer, ringkas, ekosistem plugin kayadoctest: memvalidasi contoh di docstring
Contoh unittest (secara historis juga disebut pyunit):
import unittest
def multiply(a, b):
return a * b
class TestMultiply(unittest.TestCase):
def test_multiply(self):
self.assertEqual(multiply(3, 4), 12)
if __name__ == "__main__":
unittest.main()
Contoh test pytest sederhana:
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5
Test yang mudah dibaca sebaiknya menjelaskan behavior, bukan detail implementasi.
Pola Arrange-Act-Assert
Sebagian besar unit test mengikuti tiga langkah:
- Arrange state input
- Act dengan memanggil function
- Assert output yang diharapkan
def test_discount_price():
price = 100
discount = 0.2
result = price * (1 - discount)
assert result == 80
Struktur ini membuat test konsisten dan mudah dibaca.
Coverage dan confidence
Coverage memberi tahu seberapa banyak kode yang dieksekusi saat testing. Ini sinyal, bukan jaminan.
python -m pip install coverage
coverage run -m pytest
coverage report -m
Coverage tinggi berguna, tetapi assertion yang bermakna lebih penting daripada persentase.
Panduan langkah demi langkah
Langkah 1 — Buat module yang mudah diuji
Buat calculator.py:
def divide(a: float, b: float) -> float:
if b == 0:
raise ValueError("b must not be zero")
return a / b
Function kecil yang murni paling mudah untuk diuji.
Langkah 2 — Tambahkan test pytest
Buat test_calculator.py:
import pytest
from calculator import divide
def test_divide_success():
assert divide(10, 2) == 5
def test_divide_by_zero():
with pytest.raises(ValueError):
divide(10, 0)
Jalankan test:
pytest -q
Langkah 3 — Tambahkan coverage dan cek lintas environment
coverage run -m pytest
coverage report -m
Konfigurasi tox opsional (untuk cek multi-versi):
[tox]
envlist = py311, py312
[testenv]
deps = pytest
commands = pytest
Ini membantu memverifikasi behavior pada versi Python yang didukung.
Struktur project pytest sederhana:
my_project/
├── src/
│ └── calculator.py
├── tests/
│ └── test_calculator.py
├── pyproject.toml
└── README.md
Contoh praktis
Contoh 1 — Parameterized tests untuk banyak input
import pytest
@pytest.mark.parametrize(
"a,b,expected",
[
(1, 2, 3),
(10, 5, 15),
(-1, 1, 0),
],
)
def test_add_cases(a, b, expected):
assert a + b == expected
Expected result:
3 passed
Contoh 2 — Doctest untuk dokumentasi yang dapat dieksekusi
def square(value: int) -> int:
"""
Return square of a number.
>>> square(4)
16
>>> square(-3)
9
"""
return value * value
Jalankan doctest:
python -m doctest -v your_module.py
Ini menjaga contoh dan behavior tetap selaras.
Contoh 3 — Siklus mini TDD (Red -> Green -> Refactor)
Mulai dengan menulis test yang gagal (Red):
def test_is_even():
assert is_even(4) is True
assert is_even(5) is False
Lalu implementasikan kode minimal agar lulus (Green):
def is_even(value):
return value % 2 == 0
Terakhir, perbaiki nama/struktur tanpa merusak test (Refactor).
Expected result:
- Test lulus setelah implementasi, dan tetap lulus setelah refactor yang aman.
Kesalahan umum dan cara menghindarinya
- Menulis test hanya untuk happy path -> Tambahkan edge case dan failure case.
- Terlalu banyak assertion dalam satu test -> Jaga test tetap fokus pada satu behavior.
- Mengikat test ke detail implementasi internal -> Uji behavior publik, bukan internal privat.
- Menjadikan persentase coverage sebagai kualitas absolut -> Kombinasikan coverage dengan assertion bermakna.
Latihan cepat
- Tulis test untuk function
safe_divide(a, b)termasuk penanganan pembagian nol. - Ubah satu pola test berulang menjadi
pytest.mark.parametrize. - Buat coverage report dan identifikasi satu branch yang belum diuji untuk ditingkatkan.
Ringkasan utama
- Test adalah safety net yang mempercepat development dan refactor.
pytestmenawarkan default praktis untuk banyak tim Python.- Coverage adalah panduan yang berguna tetapi tidak menggantikan desain test yang matang.
- Test kecil dengan ruang lingkup jelas memberi nilai jangka panjang tertinggi.
Langkah berikutnya
Lanjut ke Dokumentasi. Di panduan berikutnya, Anda akan menulis dokumentasi yang mudah dirawat dengan docstrings, Sphinx, dan workflow MkDocs.
No Comments