Ketika hasil perhitungan seharusnya persis — indeks permutasi, hasil konversi dtype, penyalinan data, atau jumlah elemen yang dihitung dari panjang list — perbandingan yang tepat adalah np.testing.assert_array_equal. Fungsi ini menuntut kesamaan bentuk dan nilai pada setiap elemen, lalu melaporkan letak ketidaksesuaian secara rinci bila ada yang meleset.

Bab ini membedah semantik “persis” milik assert_array_equal: apa saja yang diperiksa, bagaimana nan diperlakukan, serta dua aturan penting di era NumPy 2 — parameter strict=True untuk pemeriksaan dtype dan penolakan broadcasting pada shape. Pembanding yang bertoleransi dibahas terpisah pada Chapter assert_allclose.

Semantik Kesamaan Persis #

assert_array_equal(actual, desired) lulus hanya jika kedua array memiliki shape sama dan setiap elemennya identik. Satu elemen saja yang berbeda membuat fungsi memunculkan AssertionError dengan laporan yang terperinci:

python
import numpy as np
from numpy.testing import assert_array_equal

hasil = np.array([85, 90, 78])
target = np.array([85, 91, 78])
try:
    assert_array_equal(hasil, target)
    print("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: 1
Max relative difference among violations: 0.01098901
 ACTUAL: array([85, 90, 78])
 DESIRED: array([85, 91, 78])

Mari kita bedah:

  1. Baris 3-4: hasil dan target berbeda pada satu elemen — nilai 90 melawan 91 di posisi kedua.
  2. Laporan kesalahan: Mismatched elements: 1 / 3 (33.3%) menghitung berapa banyak elemen yang tidak sama, sementara dua baris berikutnya mengukur selisih maksimum — absolut 1 dan relatif 0.0109. Untuk data integer, selisih sebesar ini berarti logika yang salah, bukan galat pembulatan.
  3. Baris ACTUAL dan DESIRED: kedua array dicetak berdampingan sehingga posisi elemen yang menyimpang langsung terlihat.

Perlu ditegaskan bahwa ketika pengujian lulus, fungsi ini tidak mencetak apa pun. Keheningan setelah pemanggilan adalah tanda keberhasilan; laporan panjang hanya muncul saat gagal.

Perilaku terhadap NaN #

nan tidak sama dengan apa pun — bahkan dengan dirinya sendiri — dan di sinilah assert_array_equal berbeda dari perbandingan biasa. Fungsi testing ini memperlakukan nan sebagai angka: nan pada posisi yang sama dianggap sama:

python
import numpy as np
from numpy.testing import assert_array_equal

sensor_a = np.array([22.1, np.nan, 23.4])
sensor_b = np.array([22.1, np.nan, 23.4])
print("sensor_a == sensor_b ->", sensor_a == sensor_b)
print("np.array_equal       ->", np.array_equal(sensor_a, sensor_b))
assert_array_equal(sensor_a, sensor_b)
print("assert_array_equal   -> lulus")

Output yang Dihasilkan:

text
sensor_a == sensor_b -> [ True False  True]
np.array_equal       -> False
assert_array_equal   -> lulus

Bedah baris demi baris:

  1. Baris 6: perbandingan == mengikuti sifat asli nan: elemen kedua bernilai False meskipun kedua sisi sama-sama nan.
  2. Baris 7: np.array_equal secara bawaan memakai semantik yang sama (equal_nan=False), sehingga mengembalikan False — dua array yang identik dianggap berbeda hanya karena ada nan.
  3. Baris 8-9: assert_array_equal menolak semantik itu demi keperluan pengujian: nan pada posisi yang sama dianggap cocok, dan pemanggilan lulus tanpa error.

Parameter strict=True #

Secara bawaan, assert_array_equal tidak mempedulikan dtype: array int64 dan float64 dengan nilai sama dianggap lolos. Untuk pengujian yang juga menuntut tipe data sama, NumPy menyediakan parameter strict=True:

python
import numpy as np
from numpy.testing import assert_array_equal

utuh = np.array([1, 2, 3])
pecah = np.array([1.0, 2.0, 3.0])
try:
    assert_array_equal(utuh, pecah)
    print("int64 vs float64: lulus")
except AssertionError:
    print("int64 vs float64: tidak lulus")
try:
    assert_array_equal(utuh, pecah, strict=True)
    print("strict=True: lulus")
except AssertionError as e:
    print("strict=True: AssertionError")

Output yang Dihasilkan:

text
int64 vs float64: lulus
strict=True: AssertionError

Bedah baris demi baris:

  1. Baris 3-4: kedua array memuat nilai yang sama persis, tetapi dtype-nya berbeda — int64 melawan float64.
  2. Baris 6-9: tanpa strict, pengujian lulus karena nilai elemennya memang sama; dtype dianggap detail yang boleh berbeda.
  3. Baris 10-13: dengan strict=True, kesamaan dtype menjadi syarat; pesan kesalahannya eksplisit: (dtypes int64, float64 mismatch). Blok except mencetak keterangan singkat karena isi pesan lengkapnya sudah kita kenal dari pola blok pertama.

Parameter strict juga mematikan perlakuan khusus terhadap scalar, sehingga pembanding menjadi sepenuhnya ketat: nilai, shape, dan dtype harus sama.

Shape Harus Sama Persis #

Sesuai namanya, assert_array_equal menuntut shape yang identik — perbandingan ini tidak melakukan broadcasting. Array (3, 1) dan (3,) memuat nilai yang sama, tetapi pengujian tetap menolaknya:

python
import numpy as np
from numpy.testing import assert_array_equal

kolom = np.array([1.0, 2.0, 3.0]).reshape(3, 1)
baris = np.array([1.0, 2.0, 3.0])
print("shape kolom:", kolom.shape, "| shape baris:", baris.shape)
try:
    assert_array_equal(kolom, baris)
except AssertionError as e:
    print("AssertionError:", e)

Output yang Dihasilkan:

text
shape kolom: (3, 1) | shape baris: (3,)
AssertionError: 
Arrays are not equal

(shapes (3, 1), (3,) mismatch)
 ACTUAL: array([[1.],
       [2.],
       [3.]])
 DESIRED: array([1., 2., 3.])

Mari kita telaah:

  1. Baris 3-5: kolom berbentuk (3, 1) hasil reshape, sedangkan baris berbentuk (3,); secara aritmetika keduanya bisa di-broadcast, tetapi pengujian bukan tempat broadcasting.
  2. Laporan kesalahan: baris (shapes (3, 1), (3,) mismatch) menunjuk ketidakcocokan bentuk secara langsung — sebelum nilai mana pun dibandingkan.
  3. Baris ACTUAL dan DESIRED: penyajian kedua array memperlihatkan perbedaan dimensi yang sesungguhnya, sesuatu yang tidak terlihat dari daftar angkanya saja.

Tabel berikut merangkum perilaku ketiga mode perbandingan yang telah kita uji:

PerbandinganNilai samaShape berbedadtype berbedanan di posisi sama
a == bper elemenbroadcastbroadcastFalse
np.array_equal(a, b)satu booleanFalsediabaikanFalse
assert_array_equal(a, b)diam (lulus)AssertionErrordiabaikanlulus
assert_array_equal(a, b, strict=True)diam (lulus)AssertionErrorAssertionErrorlulus

Pola pemilihan yang bisa dipakai: pilih assert_array_equal untuk hasil yang secara matematis harus persis, tambahkan strict=True ketika dtype bagian dari kontrak fungsi, dan pindah ke assert_allclose segera setelah hasil perhitungan menyentuh floating point. Contoh perancangan kasus uji yang menyatukan keduanya disusun pada Chapter Pengujian Operasi Numerik.