Program numerik punya karakteristik yang membuat pengujian biasa kurang pas: hasilnya array berukuran ratusan elemen, nilainya floating point yang tak pernah persis, dan kegagalan sering berupa selisih kecil yang tak terlihat mata. Modul numpy.testing dirancang khusus untuk situasi ini — asersinya memahami array, menoleransi galat floating point bila diminta, dan mencetak laporan selisih yang rinci ketika pengujian tidak lulus.

Bab ini menjelaskan mengapa assert biasa tidak memadai, lalu menuntun kita menulis asersi pertama dengan numpy.testing dan memetakan fungsi-fungsi utamanya. Tiga bab berikutnya memperdalam fungsi yang paling sering dipakai: assert_array_equal dan assert_allclose, diikuti perancangan kasus uji numerik yang utuh.

Masalah dengan assert Biasa #

Cara yang tampak alami — memakai assert bawaan Python pada hasil perbandingan array — justru berakhir di error yang membingungkan:

python
import numpy as np

hasil = np.array([0.1 + 0.2, 0.5])
harapan = np.array([0.3, 0.5])
try:
    assert hasil == harapan
    print("lulus")
except ValueError as e:
    print("ValueError:", e)

Output yang Dihasilkan:

text
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Bedah baris demi baris:

  1. Baris 3-4: hasil memuat nilai hasil hitung dan harapan nilai acuannya; keduanya array dua elemen.
  2. Baris 6 (assert hasil == harapan): pernyataan assert mengevaluasi kebenaran hasil == harapan sebagai satu nilai. Perbandingan array menghasilkan array boolean dua elemen, dan interpreter tidak berani memutuskan “kebenaran” sebuah array dengan banyak elemen — itulah makna pesan ambiguous.
  3. Baris 7-10: errornya ValueError, bukan AssertionError; blok except menangkap dan mencetaknya sehingga pola masalahnya terlihat tanpa menghentikan script.

Solusi jangka pendeknya adalah (hasil == harapan).all() — tetapi pendekatan itu tetap tidak memberi tahu elemen mana yang salah dan seberapa jauh melesetnya. Tugas itulah yang diambil alih numpy.testing.

Asersi Pertama dengan assert_array_equal #

Fungsi np.testing.assert_array_equal membandingkan dua array secara elemen demi elemen. Saat lulus, ia diam; saat tidak lulus, ia mencetak laporan selisih yang detail:

python
import numpy as np
from numpy.testing import assert_array_equal

hasil = np.array([0.1 + 0.2, 0.5, 0.75])
harapan = np.array([0.3, 0.5, 0.75])
try:
    assert_array_equal(hasil, harapan)
    print("Pengujian lulus")
except AssertionError as e:
    print("AssertionError:", e)

Output yang Dihasilkan:

text
AssertionError: 
Arrays are not equal

Mismatched elements: 1 / 3 (33.3%)
Max absolute difference among violations: 5.55111512e-17
Max relative difference among violations: 1.85037171e-16
 ACTUAL: array([0.3 , 0.5 , 0.75])
 DESIRED: array([0.3 , 0.5 , 0.75])

Mari kita bedah:

  1. Baris 3-4: kasus yang sama seperti sebelumnya, kini dengan tiga elemen dan pembanding dari numpy.testing — diimpor lewat from numpy.testing import assert_array_equal.
  2. Baris 6-7: pembanding menemukan satu elemen tidak sama persis dan memunculkan AssertionError; bila lulus, fungsi tidak mencetak apa pun — keheningan adalah tanda keberhasilan.
  3. Laporan kesalahan: baris Mismatched elements: 1 / 3 (33.3%) menghitung cakupan kesalahan, dua baris berikutnya mengukur selisih maksimum secara absolut (5.55e-17) dan relatif, lalu ACTUAL dan DESIRED mencetak kedua array berdampingan.

Dari laporan itu langsung terlihat bahwa selisihnya murni galat floating point 0.1 + 0.2, bukan kesalahan logika. Keputusan berikutnya — melonggarkan perbandingan dengan toleransi — dibahas pada Chapter assert_allclose.

Peta Fungsi numpy.testing #

Modul ini berisi keluarga fungsi yang saling melengkapi. Tabel berikut memetakan fungsi yang paling sering dipakai sepanjang section ini:

FungsiMengujiCatatan
assert_array_equalkesamaan persis elemen demi elemenNaN dianggap sama bila posisinya sama
assert_allclosekedekatan dengan toleransi rtol/atolpilihan utama untuk hasil floating point
assert_array_almost_equalkedekatan sampai decimal digit desimalgaya lama, satu parameter presisi
assert_array_lessactual < desired untuk semua elemencocok untuk pemeriksaan batas
assert_raisesexception yang diharapkan munculdipakai sebagai context manager
assert_equalkesamaan objek Python umummengerti list, dict, dan array

assert_array_almost_equal dan assert_raises #

Dua fungsi dari tabel di atas layak dicoba langsung. assert_array_almost_equal bekerja dengan parameter decimal — jumlah digit desimal yang harus sama — sedangkan assert_raises memastikan suatu exception memang muncul:

python
import numpy as np
from numpy.testing import assert_array_almost_equal

ukur = np.array([9.81234567, 9.76543210])
teori = np.array([9.81234566, 9.76543211])
try:
    assert_array_almost_equal(ukur, teori, decimal=7)
    print("decimal=7 -> lulus")
except AssertionError:
    print("decimal=7 -> tidak lulus")
try:
    assert_array_almost_equal(ukur, teori, decimal=9)
    print("decimal=9 -> lulus")
except AssertionError:
    print("decimal=9 -> tidak lulus")

Output yang Dihasilkan:

text
decimal=7 -> lulus
decimal=9 -> tidak lulus
python
import numpy as np
from numpy.testing import assert_raises

with assert_raises(ValueError):
    np.arange(3) + np.arange(4)
print("ValueError muncul sesuai harapan")

with assert_raises(np.linalg.LinAlgError):
    np.linalg.inv(np.array([[1.0, 2.0], [2.0, 4.0]]))
print("LinAlgError muncul sesuai harapan")

Output yang Dihasilkan:

text
ValueError muncul sesuai harapan
LinAlgError muncul sesuai harapan

Penjelasan kedua blok:

  1. Blok pertama, baris 6-9: selisih kedua elemen adalah 1e-8; ambang decimal=7 mengizinkan selisih hingga sekitar 1.5e-7 sehingga lulus, sementara decimal=9 menuntut ketepatan sampai 1e-9 dan pengujian tidak lulus. Semakin besar decimal, semakin ketat ujiannya.
  2. Blok kedua, baris 3-5: assert_raises dipakai sebagai context manager; kode di dalam with diharapkan memunculkan ValueError — penjumlahan array (3,) dengan (4,) yang memang error.
  3. Blok kedua, baris 7-10: kasus kedua memastikan np.linalg.inv pada matriks singular memunculkan LinAlgError. Bila kode di dalam with tidak memunculkan exception apa pun, assert_raises sendiri yang gagal.

Satu catatan penutup: assert_array_almost_equal masih banyak dipakai di kode lama, tetapi untuk kode baru pilihlah assert_allclose karena parameter rtol/atol-nya jauh lebih mudah ditafsirkan. Detail parameter itu — termasuk rumus toleransinya — menjadi topik penuh pada Chapter assert_allclose, sementara perilaku persis assert_array_equal dibedah pada Chapter assert_array_equal.