Skrip pemeriksaan manual pada Chapter Dasar-Dasar Software Testing berhenti pada kegagalan pertama dan tidak melaporkan ringkasan. pytest adalah framework test yang paling banyak dipakai di ekosistem Python untuk menghapus kedua keterbatasan tersebut: pytest menemukan test secara otomatis, menjalankan semuanya meski ada yang gagal, lalu merangkum hasilnya dalam beberapa baris. Pada Chapter ini kita menulis test pytest pertama, menjalankannya lewat terminal, dan belajar membaca output test yang gagal.
Instalasi pytest #
pytest adalah package pihak ketiga, jadi kita instal dengan pip di dalam virtual environment aktif:
python3 -m pip install pytestSeluruh contoh pada Section ini diuji dengan pytest 9.0.2 di Python 3.12. Versi dapat diperiksa dengan:
python3 -m pytest --versionOutput yang Dihasilkan:
pytest 9.0.2Test Pertama #
pytest mencari test lewat dua konvensi nama: file yang diawali test_ dan fungsi yang diawali test_. Simpan file test_kalkulator.py berikut satu folder dengan kalkulator.py:
from kalkulator import tambah, kurang
def test_tambah_angka_positif():
assert tambah(2, 3) == 5
def test_tambah_angka_negatif():
assert tambah(-1, 1) == 0
def test_kurang_mengurangi_b():
assert kurang(10, 4) == 6Tidak ada class, tidak ada method khusus — hanya fungsi biasa berisi pernyataan assert polos. pytest menjalankan setiap fungsi tersebut sebagai satu test terpisah.
Dari folder yang sama, jalankan:
python3 -m pytestOutput yang Dihasilkan:
============================= test session starts ==============================
platform linux -- Python 3.12.15, pytest-9.0.2, pluggy-1.6.0
rootdir: /tmp/belajar-testing/ch02
collected 3 items
test_kalkulator.py ... [100%]
============================== 3 passed in 0.01s ===============================Baris rootdir menampilkan folder proyek tempat pytest berjalan — isinya mengikuti lokasi proyek di masing-masing mesin. Tiga titik pada baris test_kalkulator.py ... mewakili tiga test; satu titik berarti satu test lulus.
Tiga Gaya Output #
| Perintah | Kegunaan |
|---|---|
python3 -m pytest | output standar dengan header sesi |
python3 -m pytest -v | menampilkan setiap nama test dan statusnya |
python3 -m pytest -q | mode senyap, hanya titik-titik dan ringkasan |
Bagian inti hasil -v untuk test di atas:
test_kalkulator.py::test_tambah_angka_positif PASSED [ 33%]
test_kalkulator.py::test_tambah_angka_negatif PASSED [ 66%]
test_kalkulator.py::test_kurang_mengurangi_b PASSED [100%]
============================== 3 passed in 0.01s ===============================Anatomi Test yang Gagal #
Test gagal justru adalah momen paling berguna; mari kita baca anatominya dengan sengaja menulis ekspektasi yang salah. File test_kalkulator_salah.py:
from kalkulator import tambah
def test_tambah_menghitung_dengan_benar():
assert tambah(2, 3) == 6Jalankan python3 -m pytest -q test_kalkulator_salah.py:
F [100%]
=================================== FAILURES ===================================
_____________________ test_tambah_menghitung_dengan_benar ______________________
def test_tambah_menghitung_dengan_benar():
> assert tambah(2, 3) == 6
E assert 5 == 6
E + where 5 = tambah(2, 3)
test_kalkulator_salah.py:4: AssertionError
=========================== short test summary info ============================
FAILED test_kalkulator_salah.py::test_tambah_menghitung_dengan_benar - assert...
1 failed in 0.01sEmpat penanda pada output ini perlu dihafal karena muncul di semua kegagalan pytest:
- Huruf
Fdi baris pertama: satu test gagal. Kalau lulus, posisi itu terisi titik. - Baris
> assert tambah(2, 3) == 6: penanda>menunjuk baris persis yang gagal, disalin dari source code test. - Baris
E assert 5 == 6: baris berawalanEmenampilkan hasil evaluasi nyata. Kita langsung tahutambah(2, 3)mengembalikan5, bukan6. - Baris
E + where 5 = tambah(2, 3): pytest membedah subekspresi — bagian mana yang menghasilkan nilai5. Fitur ini bernama assert rewriting dan dibahas tuntas pada Chapter Assertions.
Diff untuk Perbandingan Struktur #
Ketika kedua sisi == adalah list, pytest menampilkan letak perbedaannya secara langsung:
from kalkulator import tambah
def test_nama_pesanan():
pesanan = ["kopi", "teh", "susu"]
assert pesanan == ["kopi", "teh", "gula"]Output yang Dihasilkan (dipangkas dari run -q):
E AssertionError: assert ['kopi', 'teh', 'susu'] == ['kopi', 'teh', 'gula']
E
E At index 2 diff: 'susu' != 'gula'
E Use -v to get more diffTanpa membuka editor, pytest sudah memberi tahu bahwa perbedaan berada di indeks ke-2.
Assert Polos versus Assert dengan Pesan #
Perintah assert boleh diberi pesan tambahan setelah koma:
def test_tambah_dua_angka():
hasil = tambah(2, 3)
assert hasil == 6, "hasil seharusnya 6"Output yang Dihasilkan (dipangkas dari run -q):
E AssertionError: hasil seharusnya 6
E assert 5 == 6Pesan kustom hanya menggantikan baris pertama; pytest tetap mencetak perbandingan nilai di baris berikutnya. Karena assert rewriting sudah menjelaskan kegagalan dengan sangat rinci, kebanyakan test pytest cukup memakai assert polos tanpa pesan — pesan kustom disisipkan hanya kalau konteks bisnisnya tidak terbaca dari angka saja.
Dengan test pertama yang lulus dan test salah yang bisa dibaca anatominya, kita siap membandingkan pytest dengan alternatif bawaannya di Chapter unittest.