Tidakkah pengujian dengan satu unit saja melanggar prinsip KERING?

12

Setiap kali saya menulis tes unit, saya selalu mencoba untuk memiliki satu pernyataan per tes untuk membuat debugging lebih mudah ketika tes gagal. Namun ketika saya mengikuti aturan ini saya merasa seperti saya terus-menerus menyalin kode yang sama di setiap tes dan dengan memiliki lebih banyak tes menjadi lebih sulit untuk kembali membaca dan memelihara.

Jadi apakah pengujian dengan satu pernyataan melanggar KERING?

Dan apakah ada aturan yang baik untuk diikuti untuk menemukan keseimbangan yang baik, seperti hanya memiliki satu tes per metode ? *

* Saya menyadari mungkin tidak ada satu ukuran yang cocok untuk semua solusi untuk ini tetapi apakah ada cara yang disarankan untuk melakukan pendekatan ini?

Korey Hinton
sumber
5
Anda dapat mengekstrak kode yang Anda salin ke dalam metode
Ismail Badawi
@IsmailBadawi itu sepertinya ide yang bagus. Saya akan berasumsi metode ini harus mengembalikan instance objek kelas yang saya uji
Korey Hinton
1
Anda membuat sesuatu dalam kondisi tertentu untuk diuji? Itu terdengar seperti fixture.
Dave Hillier
@DaveHillier ya, saya belajar kata baru hari ini. Terima kasih :)
Korey Hinton
tergantung pada bagaimana Anda menginterpretasikan 1 penegasan per tes, jika Anda bermaksud satu panggilan Penegasan * maka ya jika Anda juga ingin memastikan invarian tetap berlaku (lalu ekstrak lagi ke dalam suatu metode), atau jika ada beberapa efek yang Anda bisa ' uji t dalam Assert tunggal (atau jika Anda melakukannya maka tidak akan jelas mengapa gagal)
ratchet freak

Jawaban:

14

Tes unit yang tepat memiliki konvensi penamaan yang membantu Anda segera mengidentifikasi apa yang gagal:

public void AddNewCustomer_CustomerExists_ThrowsException()

Inilah sebabnya mengapa Anda memiliki satu pernyataan per tes, sehingga setiap metode (dan namanya) sesuai dengan kondisi yang Anda nyatakan.

Seperti yang telah Anda tunjukkan dengan benar, setiap pengujian baru akan memiliki kode pengaturan yang serupa. Seperti halnya kode apa pun, Anda dapat mengubah kode umum menjadi metode sendiri untuk mengurangi atau menghilangkan duplikasi dan membuat kode Anda lebih KERING. Beberapa kerangka kerja pengujian dirancang khusus untuk memungkinkan Anda menempatkan kode pengaturan itu di satu tempat .

Di TDD, tidak ada tes yang dilakukan YAGNI, karena Anda menulis tes hanya berdasarkan apa yang Anda perlukan untuk kode Anda lakukan. Jika Anda tidak membutuhkannya, Anda tidak akan menulis tes.

Robert Harvey
sumber
Refactoring menjadi satu metode terdengar bagus. Jika saya membutuhkan instance kelas untuk berada dalam keadaan tertentu saya bisa membuat dan mengembalikan instance baru objek itu dalam metode refactored atau seperti yang Anda sarankan gunakan metode yang disediakan oleh kerangka pengujian untuk pengaturan pengujian awal.
Korey Hinton
pada titik terakhir Anda, saya yakin saya bisa menulis tes untuk fungsi saya suka kode untuk memiliki, daripada fungsi yang dibutuhkan
joelb
5

Jadi apakah pengujian dengan satu pernyataan melanggar KERING?

Tidak, tapi itu mempromosikan pelanggaran.

Yang mengatakan, desain berorientasi objek yang baik cenderung keluar jendela untuk tes unit - kebanyakan karena alasan yang baik. Lebih penting bahwa unit test diisolasi satu sama lain sehingga tes dapat diinterogasi secara terpisah dan jika perlu, diperbaiki dengan keyakinan bahwa Anda tidak melanggar tes lain. Pada dasarnya, uji kebenaran dan keterbacaan lebih penting daripada ukurannya atau kemampuan pemeliharaannya.

Terus terang, saya belum pernah menjadi penggemar dari satu pernyataan per aturan pengujian untuk alasan yang Anda jelaskan: ini mengarah ke banyak kode boilerplate yang sulit dibaca, mudah salah-boiler, dan sulit diperbaiki jika Anda refactor (yang mendorong Anda ke refactor lebih sedikit).

Jika suatu fungsi seharusnya mengembalikan daftar "foo" dan "bar" untuk input yang diberikan, tetapi dalam urutan apa pun baik-baik saja untuk menggunakan dua menegaskan untuk memeriksa bahwa keduanya dalam set hasil. Di mana Anda mendapat masalah adalah ketika tes tunggal memeriksa dua input atau dua efek samping dan Anda tidak tahu yang mana dari dua yang menyebabkan kegagalan.

Saya melihatnya sebagai variasi pada Prinsip Tanggung Jawab Tunggal: seharusnya hanya ada satu hal yang dapat menyebabkan tes gagal, dan di dunia yang ideal bahwa perubahan hanya boleh merusak satu tes.

Tapi pada akhirnya itu adalah trade off. Apakah Anda lebih cenderung menghabiskan lebih banyak waktu mempertahankan semua kode copy pastey, atau akankah Anda menghabiskan lebih banyak waktu memburu akar penyebab ketika tes dapat dipecahkan oleh berbagai sumber. Selama Anda menulis beberapa tes, mungkin tidak terlalu penting. Meskipun saya meremehkan untuk tes satu-assert, saya cenderung berbuat salah di samping lebih banyak tes. Jarak tempuh Anda mungkin beragam.

Telastyn
sumber
1
Untuk tes, lebih penting menjadi DAMP daripada KERING (Frasa Deskriptif dan Bermakna).
Jörg W Mittag
2

Tidak. Ini sepertinya seperti cara Anda melakukannya. Kecuali Anda telah menemukan referensi penting di mana mereka mengklaim ini adalah praktik yang baik.

Gunakan fixture tes (walaupun dalam terminologi XUnit set tes, setup dan teardown adalah fixture), yaitu, beberapa set up atau contoh yang berlaku untuk semua tes Anda.

Gunakan metode seperti biasanya untuk menyusun kode Anda. Ketika refactoring menguji TDD Merah-Hijau-Refactor yang biasa tidak berlaku, sebagai gantinya berlaku, "Refactoring in the Red". Itu adalah,

  1. sengaja mematahkan tes Anda,
  2. lakukan refactoring Anda
  3. perbaiki tes Anda

Dengan cara ini Anda tahu bahwa tes masih memberikan hasil positif dan negatif.

Ada beberapa format standar untuk pengujian. Misalnya, Mengatur, Bertindak, Menegaskan atau Diakui Kapan, Lalu (BDD) . Pertimbangkan untuk menggunakan fungsi terpisah untuk setiap langkah. Anda harus dapat memanggil fungsi tersebut untuk mengurangi boilerplate.

Dave Hillier
sumber