Apakah setiap tes unit dapat dijalankan secara independen dari tes lain?

24

Katakanlah Anda memiliki tes untuk dua metode kelas. Metode pertama mengumpulkan data dari tingkat lain dan memasukkannya ke dalam beberapa jenis penyimpanan yang tidak bergantung pada runtime (seperti tabel SQL), sehingga semua data yang ditangani oleh tes ini di-hardcode ke dalam tes. Metode kedua bertanggung jawab untuk mengambil data dari tempat metode pertama meninggalkannya dan mengubahnya dalam beberapa cara (perhitungan, memindahkan bagian-bagian tertentu di tempat lain, dll).

Sekarang metode kedua ini dapat memiliki input hardcoded seperti yang pertama, atau dapat diasumsikan bahwa dua tes akan dijalankan secara berurutan dan itu bisa mengambil di mana tes pertama pergi, mengambil data yang benar-benar disimpan oleh tes pertama.

Jika Anda menggunakan opsi kedua, Anda akan benar-benar memiliki ide bagus bahwa kedua metode tersebut bekerja bersama dengan baik, namun, jika tes pertama gagal, semua tes setelahnya akan gagal, menghilangkan manfaat pengujian membantu mengisolasi bug lebih cepat.

Jika Anda menggunakan opsi pertama, setiap metode akan diisolasi dan diuji secara independen, tetapi Anda tidak akan pernah benar-benar tahu bahwa mereka benar-benar dapat bekerja sama dengan benar.

Mana pilihan yang lebih baik di sini? Apakah ada semacam alternatif seperti memiliki tes tunggal untuk setiap metode yang diisolasi dengan hardcoding, dan kemudian tes yang lebih besar yang mengandung kedua metode dalam satu?

Morgan Herlocker
sumber
2
Saya benar-benar berharap saya bisa dengan mudah mengacak urutan tes unit setiap kali dijalankan. Saat ini mereka berjalan dalam beberapa perintah yang tidak diketahui, meskipun relatif tetap.
Pekerjaan

Jawaban:

11

Jika Anda menggunakan opsi pertama, setiap metode akan diisolasi dan diuji secara independen, tetapi Anda tidak akan pernah benar-benar tahu bahwa mereka benar-benar dapat bekerja sama dengan benar.

Jika metode Anda benar-benar independen, ini seharusnya tidak masalah. Metode kedua Anda harus:

a) Bekerja dengan benar saat disajikan dengan data yang valid.

b) Gagal secara masuk akal dan konsisten ketika disajikan dengan data yang tidak valid.

Sama halnya, metode pertama Anda harus melakukan hal yang sama. Jadi selama Anda menangani kasus kesalahan mereka akan bekerja sama dengan benar.

Jika Anda ingin menguji apakah metode tersebut bekerja dengan benar bersama maka itu adalah pengujian integrasi, bukan pengujian unit.

ChrisF
sumber
27

Jika tes tidak dapat berjalan secara independen maka itu bukan tes unit.

Tes unit tidak boleh bergantung pada keadaan eksternal apa pun, seperti konten tabel database. Ini harus murni menguji satu unit kode secara terpisah.

Pengujian yang mengubah atau mensyaratkan kondisi tertentu valid, mereka dapat membentuk beberapa bagian dari pengujian integrasi misalnya, dan dalam kasus seperti itu penting untuk memastikan bahwa pengaturan yang tepat dilakukan, tetapi ini tidak akan menjadi unit test. Dalam hal ini saya masih tidak menyarankan bahwa satu tes memerlukan yang lain untuk dijalankan. Jika Anda berada dalam kasus ini, Anda mungkin harus memfaktorkan kode yang diperlukan ke dalam metode pengaturan terpisah. Anda mungkin memiliki satu tes yang kemudian hanya memanggil kode pengaturan dan memverifikasi tidak ada pengecualian yang dilemparkan, misalnya, dan kemudian tes lain yang secara aktif menggunakan pengaturan data dalam metode pengaturan.

Steve
sumber
@Steve, jadi dalam contoh ini, apakah Anda akan mengatakan: satu tes untuk metode 1, satu tes untuk metode 2, dan satu tes yang menjalankan 1 dan 2 dalam tes yang sama?
Morgan Herlocker
2
Iya nih. dua yang pertama akan menjadi unit test, yang ketiga terdengar seperti tes integrasi.
Steve
jika Anda memiliki modul pelanggan dan modul pesanan dan pesanan tidak dapat dibuat tanpa hubungan dengan pelanggan. Bagaimana Anda mengujinya secara independen dari modul pelanggan: membuat catatan pelanggan dalam database dengan sql (masukkan ke pelanggan) atau gunakan Customer.createCustomer (). Dan IMHO menggunakan yang kedua lebih baik, karena Anda tidak perlu menerapkan logika apa pun dalam pengujian, tetapi itu hanya berfungsi jika pengujian Anda untuk membuat pelanggan lulus.
Dainius
@Dainius. Dalam skenario pengujian unit, Anda biasanya akan menggunakan objek tiruan, sehingga Anda akan melewati pelanggan tiruan ke modul pesanan Anda. Anda benar karena Anda tidak ingin menggunakan sql dalam hal ini.
Steve
tampaknya dalam skenario mana pun di mana metode B bergantung pada metode A, hampir selalu ada metode C yang memanggil A lalu memanggil B. Karena ini adalah kasusnya, Anda dapat menguji A, B, dan C secara independen.
Morgan Herlocker
9

Saya yakin tampaknya OK sekarang untuk memiliki unit test B yang tergantung pada keadaan yang ditinggalkan oleh unit test B. Tetapi pertimbangkan satu tahun dari sekarang ketika Anda memiliki seribu unit test. Apakah Anda benar-benar ingin menunggu selama sepuluh menit untuk menyelesaikan seluruh rangkaian tes setiap kali Anda perlu melakukan perubahan?

Itu tergantung pada gaya pengembangan Anda tentu saja, tetapi jika Anda menginginkan harapan pengembangan yang didorong oleh tes yang layak, di mana Anda mungkin menjalankan tes individual berkali-kali ketika mengembangkan fitur, saya sarankan Anda memberikan setiap tes kemampuan untuk berdiri sendiri.

Steve Rukuts
sumber
1
+1 Raskolnikov, saya tidak mempertimbangkan fakta bahwa ini akan menjadi waktu yang sangat berat di kemudian hari ketika saya "menjalankan semua tes" nanti di telepon.
Morgan Herlocker
3

Kedengarannya seperti Anda sedang berbicara tentang pengaturan tes, yang dapat dilakukan dengan beberapa cara. Anda ingin salinan data pengujian yang bersih (disebut fixture) untuk setiap tes, sehingga masing-masing tidak boleh saling bergantung.

Ada beberapa kerangka kerja yang memungkinkan jenis pengujian ini, dan alat-alat seperti DBUnit yang memungkinkan Anda untuk membangun & menghancurkan struktur data dengan cepat pada awal dan akhir pengujian dan suite pengujian.

TrueDub
sumber