Minitest adalah framework pengujian yang disertakan sebagai bagian dari pustaka standar Ruby, sehingga uji otomatis dapat ditulis tanpa menginstal gem tambahan. Topik ini membahas struktur berkas uji Minitest, assertion utama yang digunakan untuk memeriksa perilaku kode, cara menjalankan berkas uji dari terminal, serta pola penyusunan metode uji yang rapi. Setelah membacanya, sebuah kelas sederhana dapat diuji ulang secara otomatis setiap kali kodenya berubah.
Berkas uji pertama#
Minitest mulai bekerja setelah pustaka minitest/autorun dimuat. Pustaka tersebut memasang hook yang pada akhir program menjalankan seluruh kelas uji yang terdefinisi, sehingga berkas uji tidak memerlukan kode pemanggil apa pun. Kelas uji ditulis sebagai kelas biasa yang mewarisi Minitest::Test, dan setiap metode yang namanya diawali test_ dihitung sebagai satu uji. Konvensi penamaannya juga tetap: berkas uji diberi akhiran _test.rb agar perannya langsung terbaca dari namanya.
Kelas yang diuji pada topik ini adalah Kalkulator dengan empat metode yang masing-masing akan menyentuh satu kelompok assertion.
class Kalkulator
def tambah(a, b)
a + b
end
def bagi(a, b)
a / b
end
def dibagi_habis?(a, b)
(a % b).zero?
end
def akar(n)
n.negative? ? nil : Math.sqrt(n)
end
endBerkas tersebut tidak mencetak apa pun ketika dijalankan, karena tugasnya hanya mendefinisikan kelas. Perhatikan dua perilaku yang sengaja disertakan sebagai bahan uji: pembagian dua bilangan bulat pada bagi membulatkan hasilnya, dan akar mengembalikan nil untuk bilangan negatif. Berkas uji berikut memeriksa keempat metode itu.
# tidak-dijalankan: keluaran penuh uji ditampilkan pada blok bash di bawah dengan seed tetap
require "minitest/autorun"
require_relative "kalkulator"
class KalkulatorTest < Minitest::Test
def test_tambah_mengembalikan_jumlah_dua_bilangan
kalkulator = Kalkulator.new
hasil = kalkulator.tambah(2, 3)
assert_equal 5, hasil
end
def test_bagi_membulatkan_hasil_pembagian_bilangan_bulat
kalkulator = Kalkulator.new
assert_equal 2, kalkulator.bagi(5, 2)
end
def test_bagi_nol_menimbulkan_zero_division_error
kalkulator = Kalkulator.new
assert_raises(ZeroDivisionError) { kalkulator.bagi(5, 0) }
end
def test_dibagi_habis_mengembalikan_nilai_kebenaran
kalkulator = Kalkulator.new
assert kalkulator.dibagi_habis?(10, 2)
refute kalkulator.dibagi_habis?(10, 3)
end
def test_akar_bilangan_negatif_mengembalikan_nil
kalkulator = Kalkulator.new
assert_nil kalkulator.akar(-4)
end
endBerkas uji dijalankan seperti berkas Ruby biasa, yaitu dengan menyebut namanya setelah perintah ruby. Pipa sed pada perintah berikut membuang baris waktu eksekusi yang nilainya berbeda pada setiap eksekusi, sehingga keluaran yang diperlihatkan berfokus pada hasil uji.
# menjalankan seluruh metode uji pada kalkulator_test.rb
ruby kalkulator_test.rb --seed 456 2>&1 | sed '/^Finished in/d'Run options: --seed 456
# Running:
.....
5 runs, 6 assertions, 0 failures, 0 errors, 0 skipsBaris Run options menampilkan opsi eksekusi, lima titik menyatakan lima metode uji yang berhasil berjalan, dan baris terakhir merangkum semuanya: lima uji dengan enam assertion, tanpa failure, error, atau skip. Angka failure menghitung uji yang assertion-nya terbukti keliru, angka error menghitung uji yang terputus oleh exception, sedangkan skip menghitung uji yang sengaja dilewati. Semua angka nol pada tiga kolom terakhir adalah keadaan yang dituju setiap kali uji dijalankan.
Assertion utama Minitest#
Assertion adalah pernyataan yang memeriksa sebuah dugaan tentang kode dan menandai uji sebagai gagal apabila dugaan itu tidak terbukti. Minitest menyediakan assertion dalam bentuk metode biasa, dan setiap assertion menghasilkan pesan kegagalan yang berbeda sesuai maksudnya. Tabel berikut merangkum lima assertion yang paling sering digunakan beserta pemeriksaannya.
| Assertion | Pemeriksaan yang dilakukan |
|---|---|
assert_equal 5, hasil | nilai aktual sama dengan nilai yang diharapkan |
assert kondisi | kondisi bernilai benar |
refute kondisi | kondisi bernilai salah |
assert_raises(KelasError) { ... } | blok menimbulkan kelas error yang disebutkan |
assert_nil nilai | nilai yang diperiksa adalah nil |
Pasangan assert dan refute menangani nilai kebenaran. Metode test_dibagi_habis_mengembalikan_nilai_kebenaran menggunakan keduanya: assert untuk dibagi_habis?(10, 2) yang memang benar, dan refute untuk dibagi_habis?(10, 3) yang memang salah. Kedua pemanggilan itu tetap bisa ditulis dengan assert dan tanda !, tetapi refute menyatakan maksudnya lebih langsung dan pesan kegagalannya lebih informatif.
assert_raises memeriksa exception. Pemanggilan bagi(5, 0) pada pembagian bilangan bulat menimbulkan ZeroDivisionError, dan assertion dalam bentuk blok memastikan error itu benar-benar terjadi. Apabila blok tidak menimbulkan exception apa pun atau menimbulkan kelas yang berbeda, uji dinyatakan gagal. Sementara itu, assert_nil memeriksa nilai nil secara khusus: akar(-4) sengaja dirancang mengembalikan nil, dan assert_nil menyatakan pemeriksaan itu dengan lebih tegas daripada assert_equal nil, .... Kaidahnya sederhana, yaitu memilih assertion yang paling spesifik untuk pemeriksaan yang diinginkan, karena pesan kegagalannya pun menjadi lebih jelas.
Pola arrange-act-assert#
Metode uji yang mudah dibaca mengikuti pola arrange-act-assert, yaitu menyusun keadaan awal, menjalankan perilaku yang diuji, lalu memeriksa hasilnya. Metode test_tambah_mengembalikan_jumlah_dua_bilangan memperlihatkan ketiganya dalam tiga baris: baris pertama menyusun objek Kalkulator, baris kedua menjalankan tambah(2, 3), dan baris ketiga memeriksa hasilnya terhadap 5. Bentuk tiga baris seperti ini dimungkinkan karena hasil metode disimpan ke variabel lokal terlebih dahulu. Bentuk ringkas yang menggabungkan pemanggilan ke dalam assertion, seperti pada test_bagi_membulatkan_hasil_pembagian_bilangan_bulat, juga lazim digunakan untuk pemeriksaan yang pendek.
Disiplin yang menyertainya adalah satu metode uji untuk satu perilaku. Nama metode uji diperlakukan sebagai deskripsi perilaku, sehingga apabila sebuah uji gagal, penyebabnya terbaca langsung dari namanya tanpa membuka isi metodenya. Metode test_dibagi_habis_mengembalikan_nilai_kebenaran memuat dua assertion, dan hal itu tetap wajar karena keduanya memeriksa satu perilaku yang sama, yaitu nilai kembalian yang benar untuk dua kasus berlawanan.
Kesalahan umum#
Kesalahan yang paling sering luput adalah menamai metode uji tanpa prefiks test_. Metode seperti itu tidak dihitung sebagai uji, dan Minitest tetap melaporkan hasil yang tampak sukses karena memang tidak ada uji yang berjalan. Berkas berikut memuat metode bernama cek_tambah, yang secara isi identik dengan uji penjumlahan tetapi tidak pernah dieksekusi.
# tidak-dijalankan: keluaran penuh uji ditampilkan pada blok bash di bawah dengan seed tetap
require "minitest/autorun"
require_relative "kalkulator"
class KalkulatorTanpaPrefiksTest < Minitest::Test
def cek_tambah
kalkulator = Kalkulator.new
assert_equal 5, kalkulator.tambah(2, 3)
end
end# menjalankan berkas uji yang metodenya tidak berprefiks test_
ruby uji_tanpa_prefiks.rb --seed 456 2>&1 | sed '/^Finished in/d'Run options: --seed 456
# Running:
0 runs, 0 assertions, 0 failures, 0 errors, 0 skipsKeluaran menyatakan 0 runs, dan itulah tanda yang harus dicurigai: tidak ada satu uji pun yang berjalan, sehingga laporan tanpa failure tidak berarti apa-apa. Perbaikannya adalah mengganti nama cek_tambah menjadi test_tambah beserta penyesuaian deskripsinya, sehingga metode tersebut terhitung sebagai uji. Kesalahan serupa yang lain terjadi ketika require "minitest/autorun" lupa ditulis, dan definisi kelas langsung berakhir dengan NameError karena konstanta Minitest belum dikenal. Kedua kasus ini menegaskan satu kebiasaan yang sehat, yaitu selalu membaca angka runs pada akhir keluaran, bukan hanya ketiadaan failure.
Ringkasan#
- Berkas uji Minitest memuat
require "minitest/autorun"serta kelas yang mewarisiMinitest::Test, dan dijalankan langsung denganruby nama_berkas_test.rb. - Metode uji wajib diawali
test_agar dihitung sebagai uji, sedangkan opsi--seedmenetapkan urutan eksekusinya. - Assertion utama adalah
assert_equal,assert,refute,assert_raises, danassert_nil, dengan kaidah memilih bentuk yang paling spesifik. - Pola arrange-act-assert dan satu perilaku per metode uji menjaga diagnosis tetap cepat, dan angka
runspada keluaran wajib dipastikan bukan nol.
Referensi#
- minitest — GitHub — Repositori resmi Minitest beserta gambaran assertion dan cara penggunaannya.
- Minitest — docs.seattlerb.org — Dokumentasi resmi Minitest, termasuk panduan penulisan spesifikasi dan daftar assertion lengkap.