it-swarm-id.com

Apa yang harus Anda uji dengan unit test?

Saya baru saja lulus dari perguruan tinggi, dan memulai universitas di suatu tempat minggu depan. Kami telah melihat unit test, tetapi kami agak tidak menggunakannya; dan semua orang membicarakannya, jadi saya pikir mungkin saya harus melakukan beberapa.

Masalahnya adalah, saya tidak tahu apa untuk menguji. Haruskah saya menguji kasus umum? Kasing Tepi? Bagaimana saya tahu bahwa suatu fungsi tercakup secara memadai?

Saya selalu memiliki perasaan mengerikan bahwa sementara tes akan membuktikan bahwa suatu fungsi berfungsi untuk kasus tertentu, sama sekali tidak berguna untuk membuktikan bahwa fungsi tersebut berfungsi, titik.

128
zneak

Filosofi pribadi saya sejauh ini adalah:

  1. Uji kasus umum dari semua yang Anda bisa. Ini akan memberi tahu Anda ketika kode itu rusak setelah Anda melakukan beberapa perubahan (yang, menurut pendapat saya, satu-satunya manfaat terbesar dari pengujian unit otomatis).
  2. Uji kasus Edge dari beberapa kode rumit luar biasa yang menurut Anda mungkin akan memiliki kesalahan.
  3. Setiap kali Anda menemukan bug, tulis test case untuk menutupnya sebelum memperbaikinya
  4. Tambahkan tes kasus tepi ke kode yang kurang kritis setiap kali seseorang memiliki waktu untuk membunuh.
124
Fishtoaster

Di antara kebanyakan jawaban, sejauh ini tidak ada yang menyinggung partisi kesetaraan dan analisis nilai batas , pertimbangan penting dalam jawaban untuk pertanyaan yang ada. Semua jawaban lain, meskipun bermanfaat, bersifat kualitatif tetapi dimungkinkan - dan lebih disukai - untuk menjadi kuantitatif di sini. @fishtoaster memberikan beberapa pedoman konkret, hanya mengintip di balik selimut kuantifikasi uji, tetapi partisi kesetaraan dan analisis nilai batas memungkinkan kita untuk melakukan lebih baik.

Dalam partisi kesetaraan , Anda membagi set semua input yang mungkin menjadi grup berdasarkan hasil yang diharapkan. Setiap input dari satu grup akan menghasilkan hasil yang setara, sehingga grup tersebut disebut kelas ekivalensi. (Perhatikan bahwa hasil yang setara tidak tidak berarti hasil yang identik.)

Sebagai contoh sederhana, pertimbangkan sebuah program yang harus mengubah huruf kecil ASCII karakter menjadi huruf besar. Karakter lain harus menjalani transformasi identitas, mis. Tetap tidak berubah. Berikut adalah kemungkinan pengelompokan ke dalam kelas kesetaraan:

| # |  Equivalence class    | Input        | Output       | # test cases |
+------------------------------------------------------------------------+
| 1 | Lowercase letter      | a - z        | A - Z        | 26           |
| 2 | Uppercase letter      | A - Z        | A - Z        | 26           |
| 3 | Non-alphabetic chars  | [email protected]#,/"... | [email protected]#,/"... | 42           |
| 4 | Non-printable chars   | ^C,^S,TAB... | ^C,^S,TAB... | 34           |

Kolom terakhir melaporkan jumlah kasus uji jika Anda menyebutkan semuanya. Secara teknis, dengan aturan @ fishtoaster 1 Anda akan memasukkan 52 kasus uji - semua untuk dua baris pertama yang diberikan di atas termasuk dalam "kasus umum". Aturan @ fishtoaster 2 akan menambahkan beberapa atau semua dari baris 3 dan 4 di atas juga. Tetapi dengan pengujian partisi ekivalensi setiap satu test case di setiap kelas kesetaraan sudah cukup. Jika Anda memilih "a" atau "g" atau "w" Anda sedang menguji jalur kode yang sama. Dengan demikian, Anda memiliki total 4 kasus uji, bukannya 52+.

Analisis nilai batas merekomendasikan sedikit perbaikan: pada dasarnya ini menunjukkan bahwa tidak setiap anggota kelas ekuivalensi, yah, setara. Artinya, nilai pada batas juga harus dianggap layak untuk kasus uji dalam hak mereka sendiri. (Satu pembenaran mudah untuk ini adalah yang terkenal kesalahan off-by-one !) Jadi, untuk setiap kelas ekivalensi Anda dapat memiliki 3 input uji. Melihat domain input di atas - dan dengan sedikit pengetahuan tentang nilai ASCII nilai - saya mungkin menemukan input case test ini:

| # | Input                | # test cases |
| 1 | a, w, z              | 3            |
| 2 | A, E, Z              | 3            |
| 3 | 0, 5, 9, !, @, *, ~  | 7            |
| 4 | nul, esc, space, del | 4            |

(Segera setelah Anda mendapatkan lebih dari 3 nilai batas yang menunjukkan Anda mungkin ingin memikirkan kembali delineasi kelas ekuivalensi asli Anda, tapi ini cukup sederhana sehingga saya tidak kembali untuk merevisinya.) Dengan demikian, analisis nilai batas membawa kita ke hanya 17 uji kasus - dengan keyakinan tinggi cakupan penuh - dibandingkan dengan 128 uji kasus untuk melakukan pengujian lengkap. (Belum lagi bahwa kombinatorik mendikte bahwa pengujian lengkap hanya tidak layak untuk aplikasi dunia nyata!)

68
Michael Sorens

Mungkin pendapat saya tidak terlalu populer. Tetapi saya menyarankan Anda untuk berhemat dengan unit test. Jika Anda memiliki terlalu banyak unit test, Anda dapat dengan mudah menghabiskan setengah dari waktu Anda atau lebih dengan mempertahankan tes daripada pengkodean yang sebenarnya.

Saya menyarankan Anda untuk menulis tes untuk hal-hal yang Anda punya firasat buruk di usus Anda atau hal-hal yang sangat penting dan/atau dasar. Tes unit IMHO bukan pengganti untuk rekayasa yang baik dan pengkodean defensif. Saat ini saya mengerjakan proyek yang kurang lebih tidak dapat digunakan. Ini benar-benar stabil tetapi sakit untuk refactor. Sebenarnya tidak ada yang menyentuh kode ini dalam satu tahun dan tumpukan perangkat lunak yang didasarkan pada adalah 4 tahun. Mengapa? Karena itu berantakan dengan tes unit, tepatnya: Tes unit dan tes integrasi terotomatisasi. (Pernah mendengar mentimun dan sejenisnya?) Dan inilah bagian terbaiknya: Perangkat lunak (yang) tidak dapat digunakan ini telah dikembangkan oleh sebuah perusahaan yang karyawannya adalah pelopor dalam kancah pengembangan yang didorong oleh uji coba. : D

Jadi saran saya adalah:

  • Mulai tes menulis setelah Anda mengembangkan kerangka dasar, jika tidak, refactoring bisa menyakitkan. Sebagai pengembang yang mengembangkan untuk orang lain, Anda tidak pernah mendapatkan persyaratan sejak awal.

  • Pastikan unit test Anda dapat dilakukan dengan cepat. Jika Anda memiliki tes integrasi (seperti mentimun) tidak apa-apa jika perlu waktu lebih lama. Tapi tes berjalan lama tidak menyenangkan, percayalah. (Orang-orang lupa semua alasan mengapa C++ menjadi kurang populer ...)

  • Serahkan hal-hal TDD ini kepada para ahli TDD.

  • Dan ya, kadang-kadang Anda berkonsentrasi pada kasing Edge, terkadang pada kasing umum, tergantung di mana Anda mengharapkan yang tak terduga. Meskipun jika Anda selalu mengharapkan yang tidak terduga, Anda harus benar-benar memikirkan kembali alur kerja dan disiplin Anda. ;-)

20
Philip

Jika Anda menguji terlebih dahulu dengan Test Driven Development, maka cakupan Anda akan naik di kisaran 90% atau lebih tinggi, karena Anda tidak akan menambahkan fungsionalitas tanpa terlebih dahulu menulis unit test yang gagal untuknya.

Jika Anda menambahkan tes setelah fakta, maka saya tidak bisa merekomendasikan cukup bahwa Anda mendapatkan salinan Bekerja Efektif dengan Kode Legacy oleh Michael Feathers dan lihat beberapa teknik untuk menambahkan tes ke kode Anda dan cara refactoring kode Anda untuk membuatnya lebih dapat diuji.

8
Paddyslacker

Jika Anda mulai mengikuti Pengembangan Didorong Uji Coba praktik, mereka akan mengurutkan memandu Anda melalui proses dan mengetahui apa yang akan diuji akan datang secara alami. Beberapa tempat untuk memulai:

Tes didahulukan

Jangan pernah menulis kode sebelum menulis tes. Lihat Merah-Hijau-Refactor-Ulangi untuk penjelasan.

Tulis tes regresi

Setiap kali Anda menemukan bug, tulis testcase, dan pastikan itu gagal . Kecuali Anda dapat mereproduksi bug melalui testcase yang gagal, Anda belum benar-benar menemukannya.

Merah-Hijau-Refactor-Ulangi

Merah : Mulailah dengan menulis tes paling dasar untuk perilaku yang Anda coba terapkan. Pikirkan langkah ini saat menulis beberapa kode contoh yang menggunakan kelas atau fungsi yang sedang Anda kerjakan. Pastikan itu mengkompilasi/tidak memiliki kesalahan sintaks dan bahwa itu gagal . Ini harus jelas: Anda belum menulis kode apa pun, jadi pasti gagal, bukan? Hal penting untuk dipelajari di sini adalah bahwa kecuali Anda melihat tes gagal setidaknya sekali, Anda tidak akan pernah yakin bahwa jika lulus, itu melakukannya karena sesuatu yang telah Anda lakukan karena beberapa alasan palsu.

Hijau : Tulis kode paling sederhana dan bodoh yang benar-benar membuat lulus ujian. Jangan mencoba menjadi pintar. Bahkan jika Anda melihat bahwa ada kasus Edge yang jelas tetapi tes memperhitungkannya, jangan menulis kode untuk menanganinya (tapi jangan lupa tentang kasus Edge: Anda ' akan membutuhkannya nanti). Idenya adalah bahwa setiap bagian dari kode yang Anda tulis, setiap if, setiap try: ... except: ... harus dibenarkan oleh test case. Kode tidak harus elegan, cepat, atau dioptimalkan. Anda hanya ingin lulus ujian.

Refactor : Bersihkan kode Anda, dapatkan nama metode yang benar. Lihat apakah tes masih berlalu. Optimalkan. Jalankan tes lagi.

Ulangi : Anda ingat kasus Edge yang tidak dicakup tes, bukan? Jadi, sekarang ini momen besar. Tulis testcase yang mencakup situasi itu, saksikan gagal, tulis beberapa kode, lihat lulus, refactor.

Uji kode Anda

Anda sedang mengerjakan beberapa kode tertentu, dan inilah yang ingin Anda uji. Ini berarti bahwa Anda tidak boleh menguji fungsi perpustakaan, perpustakaan standar atau kompiler Anda. Juga, cobalah untuk menghindari menguji "dunia". Ini termasuk: memanggil API web eksternal, beberapa hal intensif basis data, dll. Setiap kali Anda dapat mencoba untuk mengejeknya (membuat objek yang mengikuti antarmuka yang sama, tetapi mengembalikan statis, data yang telah ditentukan).

6
Ryszard Szopa

Untuk pengujian unit, mulailah dengan pengujian yang melakukan apa yang dirancang untuk dilakukan. Itu harus menjadi kasus pertama yang Anda tulis. Jika bagian dari desain adalah "harus mengeluarkan pengecualian jika Anda lulus dalam sampah", uji itu juga karena itu adalah bagian dari desain.

Mulailah dengan itu. Ketika Anda mendapatkan pengalaman dengan melakukan hal yang paling mendasar dari pengujian Anda akan mulai belajar apakah itu cukup atau tidak, dan mulai melihat aspek lain dari kode Anda yang perlu diuji.

3
Bryan Oakley

Jawaban utama adalah "uji semua yang mungkin bisa dipecahkan" .

Apa yang terlalu sederhana untuk dihancurkan? Bidang data, pengakses properti mati-otak, dan overhead boilerplate serupa. Hal lain mungkin mengimplementasikan sebagian persyaratan yang dapat diidentifikasi, dan mungkin mendapat manfaat dari pengujian.

Tentu saja, jarak tempuh Anda - dan praktik lingkungan kerja Anda - dapat bervariasi.

0
Jeffrey Hantin