Dipicu oleh utas ini , saya (sekali lagi) berpikir untuk akhirnya menggunakan unit test dalam proyek saya. Beberapa poster di sana mengatakan sesuatu seperti "Tes itu keren, jika itu tes yang bagus". Pertanyaan saya sekarang: Apa itu tes "baik"?
Dalam aplikasi saya, bagian utama sering kali adalah semacam analisis numerik, tergantung pada sejumlah besar data yang diamati, dan menghasilkan fungsi fit yang dapat digunakan untuk memodelkan data ini. Saya merasa sangat sulit untuk membuat tes untuk metode ini, karena jumlah input dan hasil yang mungkin terlalu besar untuk hanya menguji setiap kasus, dan metode itu sendiri seringkali agak gondrong dan tidak dapat dengan mudah di refactored tanpa mengorbankan kinerja. Saya terutama tertarik pada tes "baik" untuk metode semacam ini.
sumber
Jawaban:
Seni Pengujian Unit memiliki pendapat berikut tentang pengujian unit:
dan kemudian menambahkannya harus sepenuhnya otomatis, dapat dipercaya, dapat dibaca, dan dipelihara.
Saya sangat merekomendasikan membaca buku ini jika Anda belum melakukannya.
Menurut pendapat saya, semua ini sangat penting, tetapi tiga yang terakhir (dapat dipercaya, dapat dibaca, dan dipelihara) terutama, seolah-olah tes Anda memiliki tiga properti ini maka kode Anda biasanya memilikinya juga.
sumber
It should run at the push of a button
, apakah itu berarti bahwa tes unit tidak boleh mengharuskan kontainer (server aplikasi) berjalan (untuk unit yang sedang diuji) atau koneksi sumber daya (seperti DB, layanan web eksternal dll)? Saya hanya bingung bagian mana dari suatu aplikasi yang harus diuji unit dan mana yang tidak. Saya telah diberitahu bahwa tes unit tidak harus bergantung pada koneksi DB dan menjalankan wadah dan mungkin menggunakan mockup.Tes unit yang baik tidak mencerminkan fungsi yang sedang diuji.
Sebagai contoh yang sangat sederhana, anggap Anda memiliki fungsi yang mengembalikan rata-rata dua int. Tes yang paling komprehensif akan memanggil fungsi dan memeriksa apakah hasilnya ternyata rata-rata. Ini sama sekali tidak masuk akal: Anda sedang meniru (mereplikasi) fungsionalitas yang Anda uji. Jika Anda membuat kesalahan dalam fungsi utama, Anda akan membuat kesalahan yang sama dalam ujian.
Dengan kata lain, jika Anda mereplikasi fungsi utama dalam tes unit, itu adalah tanda bahwa Anda membuang-buang waktu.
sumber
Tes unit yang baik pada dasarnya adalah spesifikasi dalam bentuk runnable:
Saya telah menemukan Test-Driven-Development sangat cocok untuk rutinitas perpustakaan ketika Anda pada dasarnya menulis API terlebih dahulu, dan MAKA implementasi yang sebenarnya.
sumber
untuk TDD, fitur pengujian "baik" menguji yang diinginkan pelanggan ; fitur tidak harus sesuai dengan fungsi, dan skenario pengujian tidak boleh dibuat oleh pengembang dalam ruang hampa
dalam kasus Anda - saya menduga - 'fitur' adalah bahwa fungsi fit memodelkan data input dalam toleransi kesalahan tertentu. Karena saya tidak tahu apa yang sebenarnya Anda lakukan, saya mengarang sesuatu; semoga itu analgous.
Contoh cerita:
Jadi, Anda berbicara dengan pilot (dan ke komputer penargetan, jika hidup). Pertama Anda berbicara tentang apa yang 'normal', kemudian berbicara tentang yang tidak normal. Anda mencari tahu apa yang sebenarnya penting dalam skenario ini, apa yang umum, apa yang tidak mungkin, dan apa yang hanya mungkin.
Katakanlah bahwa biasanya Anda akan memiliki jendela setengah detik lebih dari tujuh saluran data telemetri: kecepatan, pitch, roll, menguap, vektor target, ukuran target, dan kecepatan target, dan bahwa nilai-nilai ini akan konstan atau berubah secara linear. Abnormal Anda mungkin memiliki lebih sedikit saluran dan / atau nilainya dapat berubah dengan cepat. Jadi, bersama-sama Anda membuat beberapa tes seperti:
Sekarang, Anda mungkin telah memperhatikan bahwa tidak ada skenario untuk situasi tertentu yang dijelaskan dalam cerita. Ternyata, setelah berbicara dengan pelanggan dan pemangku kepentingan lainnya, tujuan dalam cerita aslinya hanyalah contoh hipotetis. Tes nyata keluar dari diskusi berikutnya. Ini bisa terjadi. Ceritanya harus ditulis ulang, tetapi tidak harus [karena ceritanya hanyalah pengganti untuk percakapan dengan pelanggan].
sumber
Buat tes untuk kasing sudut, seperti set tes yang hanya berisi jumlah input minimum (mungkin 1 atau 0) dan beberapa kasing standar. Tes-tes unit itu bukan pengganti untuk tes penerimaan menyeluruh, juga tidak seharusnya demikian.
sumber
Saya telah melihat banyak kasus di mana orang menginvestasikan sejumlah besar upaya menulis tes untuk kode yang jarang dimasukkan, dan tidak menulis tes untuk kode yang sering dimasukkan.
Sebelum duduk untuk menulis tes apa pun, Anda harus melihat semacam grafik panggilan, untuk memastikan Anda merencanakan cakupan yang memadai.
Selain itu, saya tidak percaya pada tes menulis hanya untuk mengatakan "Ya, kami menguji itu". Jika saya menggunakan pustaka yang dijatuhkan dan akan tetap tidak berubah, saya tidak akan menyia-nyiakan tes menulis sehari untuk memastikan jeroan API yang tidak akan pernah berubah berfungsi seperti yang diharapkan, bahkan jika bagian tertentu dari skor itu tinggi pada grafik panggilan. Tes yang menggunakan perpustakaan kata (kode saya sendiri) menunjukkan ini.
sumber
Tidak begitu TDD, tetapi setelah Anda masuk ke QA Anda dapat meningkatkan tes Anda dengan mengatur kasus uji untuk mereproduksi bug yang muncul selama proses QA. Ini bisa sangat berharga ketika Anda pergi ke dukungan jangka panjang dan Anda mulai pergi ke tempat di mana Anda berisiko orang secara tidak sengaja memperkenalkan kembali bug lama. Memiliki tes untuk menangkap yang sangat berharga.
sumber
Saya mencoba agar setiap tes hanya menguji satu hal. Saya mencoba memberi setiap tes nama seperti shouldDoSomething (). Saya mencoba menguji perilaku, bukan implementasi. Saya hanya menguji metode publik.
Saya biasanya memiliki satu atau beberapa tes untuk sukses, dan kemudian mungkin beberapa tes untuk kegagalan, per metode publik.
Saya sering menggunakan mock-up. Mock-framework yang baik mungkin akan sangat membantu, seperti PowerMock. Meskipun saya belum menggunakannya.
Jika kelas A menggunakan kelas B lain, saya akan menambahkan antarmuka, X, sehingga A tidak menggunakan B secara langsung. Lalu saya akan membuat mock-up XMockup dan menggunakannya sebagai pengganti B dalam pengujian saya. Ini benar-benar membantu mempercepat pelaksanaan pengujian, mengurangi kompleksitas pengujian, dan juga mengurangi jumlah tes yang saya tulis untuk A karena saya tidak harus mengatasi kekhasan B. Saya dapat misalnya menguji bahwa A memanggil X.someMethod () alih-alih efek samping dari memanggil B.someMethod ().
Pastikan kode pengujian Anda juga bersih.
Saat menggunakan API, seperti lapisan basis data, saya akan mengejeknya dan memungkinkan mock-up untuk melemparkan pengecualian di setiap peluang yang ada pada perintah. Saya kemudian menjalankan tes satu tanpa melempar, dan dalam satu lingkaran, setiap kali melempar pengecualian pada kesempatan berikutnya sampai tes berhasil lagi. Agak seperti tes memori yang tersedia untuk Symbian.
sumber
Saya melihat bahwa Andry Lowry telah memposting metrik pengujian unit Roy Osherove; tetapi tampaknya tidak ada yang memberikan set (gratis) yang diberikan Paman Bob dalam Kode Bersih (132-133). Dia menggunakan akronim PERTAMA (di sini dengan rangkuman saya):
sumber