pytest
Dasar-dasar pytest: menulis test pertama, konvensi penamaan, dan membaca output kegagalan.
Intisari
- Test adalah fungsi biasa yang namanya diawali
test_dan berisiassert. Tidak ada class, tidak ada boilerplate. - Cukup pakai
assertbawaan Python โ pytest yang menulis ulang pesan errornya jadi informatif. - Taruh test di folder
tests/, nama filetest_*.py. - Jalankan dengan
uv run pytest. Tambah-vuntuk detail,-xuntuk berhenti di kegagalan pertama. - Konsep lanjutan (fixture, parametrize, mock) dibahas di Fase 6 โ sekarang cukup bisa menulis test sederhana.
Test pertama
uv add --dev pytest
src/kalkulator.py:
def tambah(a: int, b: int) -> int:
return a + b
tests/test_kalkulator.py:
from kalkulator import tambah
def test_tambah_dua_positif():
assert tambah(2, 3) == 5
def test_tambah_dengan_nol():
assert tambah(5, 0) == 5
def test_tambah_negatif():
assert tambah(-2, -3) == -5
uv run pytest
Kenapa assert polos sudah cukup
Di framework testing lain kamu menulis self.assertEqual(a, b),
assertIn(x, y), dan puluhan varian lain. pytest tidak butuh itu: ia me-rewrite
bytecode assert supaya bisa melaporkan nilai kedua sisi saat gagal.
def test_tambah_dua_positif():
> assert tambah(2, 3) == 6
E assert 5 == 6
E + where 5 = tambah(2, 3)
tests/test_kalkulator.py:5: AssertionError
Baris + where itulah yang membuat pytest enak dipakai โ ia menunjukkan dari mana nilai 5 datang.
Konvensi penemuan test
pytest mencari test dengan aturan sederhana. Ikuti saja, jangan dilawan:
| Hal | Aturan |
|---|---|
| File | test_*.py atau *_test.py |
| Fungsi | Diawali test_ |
| Class (kalau perlu) | Diawali Test, tanpa __init__ |
| Folder | Biasanya tests/ di root proyek |
Flag yang sering dipakai
uv run pytest # semua test
uv run pytest -v # tampilkan nama tiap test
uv run pytest -x # berhenti di kegagalan pertama
uv run pytest -k "email" # hanya test yang namanya mengandung "email"
uv run pytest tests/test_llm.py # satu file
uv run pytest tests/test_llm.py::test_parse # satu test
uv run pytest --lf # ulangi hanya test yang gagal terakhir kali
uv run pytest -s # jangan tangkap print() โ untuk debugging
--lf (last failed) adalah flag yang paling sering menyelamatkan waktu.
Saat memperbaiki bug di suite besar, kamu tidak perlu menunggu seluruh test jalan ulang โ
cukup yang tadi gagal.
Menguji bahwa error memang dilempar
import pytest
def test_pembagian_nol_melempar_error():
with pytest.raises(ZeroDivisionError):
1 / 0
def test_pesan_error_sesuai():
with pytest.raises(ValueError, match="format email tidak valid"):
validasi_email("bukan-email")
Konfigurasi minimal
Tambahkan ke pyproject.toml:
[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["src"]
addopts = "-v --strict-markers"
pythonpath = ["src"] menyelesaikan masalah paling umum bagi pemula:
ModuleNotFoundError saat test mencoba mengimpor kode aplikasi yang ada di src/.
Apa yang belum perlu sekarang
Dokumentasi pytest sangat luas. Untuk Fase 0, cukup sampai sini. Yang berikut ini akan dibahas saat Fase 6, ketika kamu benar-benar butuh:
- Fixture โ setup/teardown yang bisa dipakai ulang antar test
parametrizeโ satu fungsi test, banyak kasus inputmonkeypatch& mocking โ mengganti panggilan LLM asli dengan yang palsupytest-asyncioโ menguji fungsiasync def
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.