Saya memiliki banyak kelas yang berhubungan dengan validasi nilai. Sebagai contoh, suatu RangeValidator
kelas memeriksa apakah suatu nilai berada dalam kisaran yang ditentukan.
Setiap kelas validator berisi dua metode is_valid(value)
:, yang mengembalikan True
atau False
bergantung pada nilai, dan ensure_valid(value)
yang memeriksa nilai yang ditentukan dan tidak melakukan apa pun jika nilainya valid, atau melempar pengecualian tertentu jika nilainya tidak cocok dengan aturan yang telah ditentukan.
Saat ini ada dua unit tes yang terkait dengan metode ini:
Yang melewati nilai yang tidak valid, dan memastikan bahwa pengecualian dilemparkan.
def test_outside_range(self): with self.assertRaises(demo.ValidationException): demo.RangeValidator(0, 100).ensure_valid(-5)
Yang melewati nilai yang valid.
def test_in_range(self): demo.RangeValidator(0, 100).ensure_valid(25)
Meskipun tes kedua melakukan tugasnya — gagal jika pengecualian dilemparkan, dan berhasil jika ensure_valid
tidak melempar apa pun — fakta bahwa tidak ada assert
bagian dalam terlihat aneh. Seseorang yang membaca kode seperti itu akan segera bertanya pada dirinya sendiri mengapa ada tes yang tampaknya tidak melakukan apa-apa.
Apakah ini praktik saat ini ketika menguji metode yang tidak mengembalikan nilai dan tidak memiliki efek samping? Atau haruskah saya menulis ulang tes dengan cara yang berbeda? Atau cukup beri komentar yang menjelaskan apa yang saya lakukan?
sumber
self
referensi) dan tidak mengembalikan hasil, itu bukan fungsi murni.void
dalam banyak bahasa dan memiliki aturan konyol.) Atau, Anda dapat memiliki tak terbatas loop (yang bekerja bahkan ketika "tidak mengembalikan hasil" benar-benar berarti tidak mengembalikan hasil.unit -> unit
dalam bahasa apa pun yang menganggap unit sebagai tipe data standar alih-alih sesuatu yang ajaib khusus. Sayangnya, ia hanya mengembalikan unit dan tidak melakukan hal lain.Jawaban:
Sebagian besar kerangka uji memiliki pernyataan eksplisit untuk "Tidak melempar", misalnya Jasmine
expect(() => {}).not.toThrow();
dan nUnit dan teman juga memilikinya.sumber
Ini sangat tergantung pada bahasa dan kerangka kerja yang digunakan. Berbicara dalam hal
NUnit
, ada beberapaAssert.Throws(...)
metode. Anda dapat memberikan mereka metode lambda:yang dieksekusi di dalam
Assert.Throws
. Panggilan ke lambda kemungkinan besar akan dibungkus olehtry { } catch { }
blok dan pernyataan gagal, jika pengecualian tertangkap.Jika kerangka kerja Anda tidak menyediakan sarana ini, Anda bisa mengatasinya, dengan membungkus panggilan sendiri (Saya menulis dalam C #):
Ini membuat niat lebih jelas, tetapi mengacaukan kode sampai batas tertentu. (Tentu saja Anda dapat membungkus semua ini dalam suatu metode.) Pada akhirnya itu akan terserah Anda.
Edit
Seperti yang ditunjukkan Doc Brown dalam komentar, masalahnya bukan untuk menunjukkan bahwa metode melempar, tetapi tidak melempar. Di NUnit ada juga pernyataan untuk itu
sumber
Cukup tambahkan komentar untuk memperjelas mengapa tidak ada penegasan yang dibutuhkan dan mengapa Anda tidak melupakannya.
Seperti yang Anda lihat di jawaban lain, hal lain membuat kode lebih rumit dan berantakan. Dengan komentar di sana, programmer lain akan mengetahui maksud tes.
Yang sedang berkata, tes semacam ini harus menjadi pengecualian (tidak ada kata pun dimaksudkan). Jika Anda menemukan diri Anda menulis sesuatu seperti itu secara teratur, maka mungkin tes tersebut memberi tahu Anda bahwa desainnya tidak optimal.
sumber
Anda juga dapat menyatakan bahwa beberapa metode dipanggil (atau tidak dipanggil) dengan benar.
Contohnya:
Dalam tes Anda:
sumber