Dalam meneliti unit pengujian praktik terbaik untuk membantu menyusun pedoman untuk organisasi saya, saya telah mengalami pertanyaan apakah lebih baik atau berguna untuk memisahkan perlengkapan pengujian (kelas uji) atau untuk menyimpan semua tes untuk satu kelas dalam satu file.
Namun, saya mengacu pada "tes unit" dalam arti murni bahwa itu adalah tes kotak putih yang menargetkan kelas tunggal, satu pernyataan per tes, semua dependensi diejek, dll.
Skenario contoh adalah kelas (sebut saja Dokumen) yang memiliki dua metode: CheckIn dan CheckOut. Setiap metode mengimplementasikan berbagai aturan, dll. Yang mengontrol perilaku mereka. Mengikuti aturan satu-pernyataan-per-tes, saya akan memiliki beberapa tes untuk setiap metode. Saya bisa menempatkan semua tes dalam satu DocumentTests
kelas dengan nama seperti CheckInShouldThrowExceptionWhenUserIsUnauthorized
dan CheckOutShouldThrowExceptionWhenUserIsUnauthorized
.
Atau, saya dapat memiliki dua kelas tes terpisah: CheckInShould
dan CheckOutShould
. Dalam hal ini, nama pengujian saya akan disingkat tetapi akan diatur sehingga semua tes untuk perilaku (metode) tertentu bersamaan.
Saya yakin ada pro dan kontra untuk pendekatan baik dan saya bertanya-tanya apakah ada yang telah mengambil rute dengan beberapa file dan, jika demikian, mengapa? Atau, jika Anda memilih pendekatan file tunggal, mengapa Anda merasa lebih baik?
sumber
testResponseContainsSuccessTrue()
,testResponseContainsMyData()
dantestResponseStatusCodeIsOk()
. Anda akan memiliki mereka dalam satutestResponse()
yang telah tiga menegaskan:assertEquals(200, response.status)
,assertEquals({"data": "mydata"}, response.data)
danassertEquals(true, response.success)
Jawaban:
Ini jarang terjadi, tetapi terkadang masuk akal untuk memiliki beberapa kelas tes untuk kelas tertentu yang sedang diuji. Biasanya saya akan melakukan ini ketika pengaturan yang berbeda diperlukan, dan dibagikan di seluruh bagian dari tes.
sumber
Tidak dapat benar-benar melihat alasan kuat mengapa Anda akan membagi tes untuk satu kelas menjadi beberapa kelas uji. Karena ide mengemudi harusnya mempertahankan kohesi pada tingkat kelas, Anda juga harus berusaha keras untuk itu pada tingkat ujian. Hanya beberapa alasan acak:
sumber
Jika Anda dipaksa untuk membagi tes unit untuk kelas di beberapa file, itu mungkin merupakan indikasi bahwa kelas itu sendiri dirancang dengan buruk. Saya tidak dapat memikirkan skenario mana pun yang lebih bermanfaat untuk membagi tes unit untuk kelas yang cukup mematuhi Prinsip Tanggung Jawab Tunggal dan praktik terbaik pemrograman lainnya.
Selain itu, memiliki nama metode yang lebih panjang dalam pengujian unit dapat diterima, tetapi jika itu mengganggu Anda, Anda selalu dapat memikirkan kembali konvensi penamaan tes unit Anda untuk mempersingkat nama.
sumber
Salah satu argumen saya terhadap pemisahan tes menjadi beberapa kelas adalah bahwa menjadi lebih sulit bagi pengembang lain dalam tim (terutama mereka yang tidak begitu paham tes) untuk menemukan tes yang ada ( Ya ampun saya bertanya-tanya apakah sudah ada tes untuk ini metode? Saya ingin tahu di mana itu akan? ) dan juga di mana harus meletakkan tes baru ( saya akan menulis tes untuk metode ini di kelas ini, tetapi tidak yakin apakah saya harus meletakkannya di file baru, atau yang sudah ada satu? )
Dalam kasus di mana tes yang berbeda memerlukan pengaturan yang berbeda secara drastis, saya telah melihat beberapa praktisi TDD meletakkan "fixture" atau "setup" di kelas / file yang berbeda, tetapi bukan tes itu sendiri.
sumber
Saya berharap saya dapat mengingat / menemukan tautan di mana teknik yang saya pilih untuk diadopsi pertama kali diperlihatkan. Pada dasarnya saya membuat satu, kelas abstrak untuk setiap kelas yang diuji yang berisi perlengkapan tes bersarang (kelas) untuk setiap anggota yang diuji. Ini memberikan pemisahan yang awalnya diinginkan tetapi menyimpan semua tes dalam file yang sama untuk setiap lokasi. Selain itu, ini menghasilkan nama kelas yang memungkinkan pengelompokan dan pengurutan yang mudah dalam test runner.
Berikut adalah contoh bagaimana pendekatan ini diterapkan pada skenario asli saya:
Ini menghasilkan tes berikut yang muncul dalam daftar tes:
Karena lebih banyak tes ditambahkan, mereka mudah dikelompokkan dan disortir berdasarkan nama kelas yang juga menyimpan semua tes untuk kelas yang diuji terdaftar bersama-sama.
Keuntungan lain dari pendekatan ini yang telah saya pelajari untuk meningkatkan adalah sifat berorientasi objek dari struktur ini berarti saya dapat mendefinisikan kode di dalam startup dan metode pembersihan dari kelas dasar DocumentTests yang akan dibagikan oleh semua kelas bersarang serta di dalam masing-masing kelas bersarang untuk tes yang dikandungnya.
sumber
Cobalah untuk berpikir sebaliknya selama satu menit.
Mengapa Anda hanya memiliki satu kelas tes per kelas? Apakah Anda melakukan tes kelas atau tes unit? Apakah Anda bahkan bergantung pada kelas ?
Tes unit seharusnya menguji perilaku tertentu, dalam konteks tertentu. Fakta bahwa kelas Anda sudah memiliki
CheckIn
sarana harus ada perilaku yang membutuhkannya sejak awal.Bagaimana pendapat Anda tentang pseudo-code ini:
Sekarang Anda tidak langsung menguji
checkIn
metode ini. Alih-alih, Anda sedang menguji perilaku (yaitu untuk mengecek untungnya;)), dan jika Anda perlu melakukan refactorDocument
dan membaginya menjadi kelas yang berbeda, atau menggabungkan kelas lain ke dalamnya, file pengujian Anda masih koheren, mereka masih masuk akal karena Anda tidak pernah mengubah logika saat refactoring, hanya strukturnya.Satu file tes untuk satu kelas hanya membuat sulit untuk refactor kapan pun Anda membutuhkannya, dan tes juga kurang masuk akal dalam hal domain / logika kode itu sendiri.
sumber
Secara umum saya akan merekomendasikan berpikir tentang tes sebagai pengujian perilaku kelas daripada metode. Yaitu beberapa tes Anda mungkin perlu memanggil kedua metode di kelas untuk menguji beberapa perilaku yang diharapkan.
Biasanya saya mulai dengan satu kelas uji unit per kelas produksi, tetapi pada akhirnya dapat membagi kelas uji unit menjadi beberapa kelas uji berdasarkan perilaku yang mereka uji. Dengan kata lain saya akan merekomendasikan agar tidak memisahkan kelas uji menjadi CheckInShould dan CheckOutShould, tetapi lebih baik membelah dengan perilaku unit yang diuji.
sumber
1. Pertimbangkan apa yang kemungkinan salah
Selama pengembangan awal, Anda cukup tahu apa yang Anda lakukan dan kedua solusi mungkin akan bekerja dengan baik.
Semakin menarik ketika tes gagal setelah perubahan jauh kemudian. Ada dua kemungkinan:
CheckIn
(atauCheckOut
). Sekali lagi, baik file tunggal maupun solusi dua file tidak masalah dalam hal itu.CheckIn
danCheckOut
(dan mungkin pengujian mereka) dengan cara yang masuk akal untuk masing-masing, tetapi tidak untuk keduanya secara bersamaan. Anda telah merusak koherensi pasangan. Dalam hal ini, membagi tes lebih dari dua file akan membuatnya lebih sulit untuk memahami masalahnya.2. Pertimbangkan tes apa yang digunakan
Tes melayani dua tujuan utama:
Begitu?
Kedua perspektif ini menyarankan agar tes bersama dapat membantu, tetapi tidak akan merugikan.
sumber