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?
testing
unit-testing
dry
Korey Hinton
sumber
sumber
Jawaban:
Tes unit yang tepat memiliki konvensi penamaan yang membantu Anda segera mengidentifikasi apa yang gagal:
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.
sumber
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.
sumber
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,
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.
sumber