Saya tahu Anda tidak seharusnya menguji metode pribadi, dan jika Anda perlu melakukannya, mungkin ada kelas di sana yang menunggu untuk keluar.
Tapi, saya tidak ingin memiliki trilyun kelas hanya supaya saya dapat menguji antarmuka publik mereka dan saya menemukan bahwa untuk banyak kelas jika saya hanya menguji metode publik saya akhirnya harus mengejek banyak dependensi dan unit test adalah luar biasa dan sulit diikuti.
Saya lebih suka mengejek metode pribadi saat menguji yang publik, dan mengejek dependensi eksternal ketika menguji yang pribadi.
Apakah saya gila?
unit-testing
mocking
Fran Sevillano
sumber
sumber
Jawaban:
Anda sebagian benar - Anda tidak boleh langsung menguji metode pribadi. Metode pribadi pada kelas harus dipanggil oleh satu atau lebih metode publik (mungkin secara tidak langsung - metode pribadi yang disebut dengan metode publik dapat menggunakan metode pribadi lainnya). Karena itu, ketika menguji metode publik Anda, Anda akan menguji metode pribadi Anda juga. Jika Anda memiliki metode pribadi yang masih belum teruji, kasus pengujian Anda tidak mencukupi atau metode pribadi tidak digunakan dan dapat dihapus.
Jika Anda mengambil pendekatan pengujian kotak putih, Anda harus mempertimbangkan detail implementasi metode pribadi Anda saat menyusun tes unit di sekitar metode publik Anda. Jika Anda mengambil pendekatan kotak hitam, Anda tidak boleh menguji terhadap setiap detail implementasi baik dalam metode publik atau pribadi tetapi terhadap perilaku yang diharapkan.
Secara pribadi, saya lebih suka pendekatan kotak putih untuk tes unit. Saya dapat membuat tes untuk menempatkan metode dan kelas yang diuji di berbagai negara yang menyebabkan perilaku menarik dalam metode publik dan pribadi saya dan kemudian menyatakan bahwa hasilnya adalah apa yang saya harapkan.
Jadi - jangan mengejek metode pribadi Anda. Gunakan mereka untuk memahami apa yang perlu Anda uji untuk memberikan cakupan fungsionalitas yang Anda berikan. Ini terutama berlaku pada tingkat unit test.
sumber
Saya pikir ini ide yang sangat buruk.
Masalah dengan membuat unit test anggota pribadi, adalah bahwa itu tidak cocok dengan siklus hidup produk.
Alasan Anda MEMILIH membuat metode-metode itu privat adalah karena mereka tidak terpusat pada apa yang coba dilakukan oleh kelas Anda - hanya membantu bagaimana Anda saat ini mengimplementasikan fungsionalitas itu. Ketika Anda refactor, detail-detail pribadi tersebut kemungkinan akan berubah dan akan menyebabkan gesekan dengan refactoring.
Juga, perbedaan utama antara anggota publik dan pribadi, adalah Anda harus memikirkan API publik Anda dengan saksama, dan mendokumentasikannya dengan baik, dan memeriksanya dengan baik (pernyataan dll). Tetapi dengan API pribadi, tidak ada gunanya untuk berpikir dengan hati-hati (usaha yang sia-sia karena penggunaannya sangat lokal). Memasukkan metode pribadi ke dalam unit test berarti menciptakan ketergantungan eksternal pada metode tersebut. Berarti API harus stabil dan didokumentasikan dengan baik (karena seseorang harus mencari tahu mengapa tes unit gagal jika / ketika mereka melakukannya).
Saya menyarankan Anda:
A menghargai kecenderungan Anda untuk menguji fungsi ini dan sulit untuk mengujinya melalui API publik Anda saat ini. Tapi saya pribadi lebih menghargai modularitas daripada cakupan tes.
sumber
UnitTests menguji perilaku publik yang dapat diamati , bukan kode, di mana "publik" berarti: mengembalikan nilai dan berkomunikasi dengan dependensi.
"Unit" adalah kode apa saja, yang memecahkan masalah yang sama (atau lebih tepatnya: memiliki alasan yang sama untuk berubah). Itu bisa berupa metode tunggal atau banyak kelas.
Alasan utama mengapa Anda tidak ingin menguji
private methods
adalah: mereka adalah detail implementasi dan Anda mungkin ingin mengubahnya selama refactoring (tingkatkan kode Anda dengan menerapkan prinsip-prinsip OO tanpa mengubah fungsionalitas). Ini tepatnya ketika Anda tidak ingin unittests Anda berubah sehingga mereka dapat menjamin perilaku CuT Anda tidak berubah selama refactoring.Saya biasanya mengalami hal yang sebaliknya: Semakin kecil kelas (semakin sedikit tanggung jawab yang mereka miliki), semakin sedikit ketergantungan yang mereka miliki, dan semakin mudah pula mereka yang belum terdaftar, untuk menulis dan membaca.
Idealnya Anda menerapkan tingkat pola abstraksi yang sama untuk kelas Anda. Ini berarti kelas Anda menyediakan logika bisnis (lebih disukai sebagai "fungsi murni" yang bekerja pada parameter mereka hanya tanpa mempertahankan status sendiri) (x) atau memanggil metode pada objek lain, bukan keduanya pada saat yang bersamaan.
Dengan cara ini unittesting perilaku bisnis adalah sepotong kue dan objek "delegasi" biasanya terlalu mudah untuk gagal (tidak ada percabangan, tidak ada perubahan negara) sehingga tidak ada unittesting diperlukan dan pengujian mereka dapat diserahkan kepada tes integrasi atau modul
sumber
Unit testing memiliki nilai ketika Anda adalah satu-satunya programmer yang mengerjakan kode, terutama jika aplikasi tersebut sangat besar atau sangat kompleks. Di mana pengujian unit menjadi penting adalah ketika Anda memiliki lebih banyak programmer yang bekerja pada basis kode yang sama. Konsep pengujian unit diperkenalkan untuk mengatasi beberapa kesulitan bekerja di tim yang lebih besar ini.
Alasan bahwa unit test membantu tim yang lebih besar adalah karena kontrak. Jika kode saya membuat panggilan ke kode yang ditulis oleh orang lain, saya membuat asumsi tentang apa yang akan dilakukan oleh kode orang lain dalam berbagai situasi. Asalkan asumsi tersebut masih benar, kode saya akan tetap berfungsi, tetapi bagaimana saya tahu asumsi yang valid dan bagaimana saya tahu kapan asumsi tersebut telah berubah?
Di sinilah tes unit masuk. Penulis kelas membuat tes unit untuk mendokumentasikan perilaku yang diharapkan dari kelas mereka. Uji unit mendefinisikan semua cara valid menggunakan kelas, dan menjalankan uji unit memvalidasi kasus penggunaan ini berfungsi seperti yang diharapkan. Programmer lain yang ingin memanfaatkan kelas Anda dapat membaca tes unit Anda untuk memahami perilaku yang dapat mereka harapkan untuk kelas Anda, dan menggunakan ini sebagai dasar untuk asumsi mereka tentang cara kerja kelas Anda.
Dengan cara ini metode publik menandatangani kelas dan unit test bersama-sama membentuk kontrak antara penulis kelas dan programmer lain yang menggunakan kelas ini dalam kode mereka.
Dalam skenario ini, apa yang terjadi jika Anda memasukkan pengujian metode pribadi? Jelas itu tidak masuk akal.
Jika Anda adalah satu-satunya programmer yang bekerja pada kode Anda dan Anda ingin menggunakan unit testing sebagai cara debug kode Anda maka saya tidak melihat ada salahnya, itu hanya alat, dan Anda dapat menggunakannya dengan cara apa pun yang bekerja untuk Anda, tetapi itu bukan alasan mengapa pengujian unit diperkenalkan, dan tidak memberikan manfaat utama pengujian unit.
sumber
Sebelum menjawab pertanyaan seperti itu, Anda perlu memutuskan apa yang sebenarnya ingin Anda capai.
Anda menulis kode. Anda berharap itu memenuhi kontraknya (dengan kata lain, itu melakukan apa yang seharusnya dilakukan. Menulis apa yang seharusnya dilakukan adalah langkah besar bagi sebagian orang).
Agar cukup yakin bahwa kode melakukan apa yang seharusnya dilakukan, Anda cukup menatapnya, atau menulis kode uji yang menguji cukup banyak kasus untuk meyakinkan Anda "jika kode tersebut lulus semua tes ini maka itu benar".
Seringkali Anda hanya tertarik pada antarmuka yang ditentukan untuk umum dari beberapa kode. Jika saya menggunakan perpustakaan Anda, saya tidak peduli bagaimana Anda membuatnya bekerja dengan benar, hanya itu tidak bekerja dengan benar. Saya memverifikasi bahwa perpustakaan Anda benar dengan melakukan tes unit.
Tetapi Anda sedang membuat perpustakaan. Membuatnya berfungsi dengan benar bisa jadi sulit untuk dicapai. Katakanlah saya hanya peduli dengan perpustakaan yang melakukan operasi X dengan benar, jadi saya memiliki unit test untuk X. Anda, pengembang yang bertanggung jawab untuk membuat perpustakaan, mengimplementasikan X dengan menggabungkan langkah A, B dan C, yang masing-masing sama sekali tidak berguna. Agar perpustakaan Anda berfungsi, Anda menambahkan tes untuk memverifikasi bahwa A, B, dan C masing-masing berfungsi dengan benar. Anda ingin tes ini. Mengatakan "Anda seharusnya tidak memiliki tes unit untuk metode pribadi" tidak ada gunanya. Anda ingin tes untuk metode pribadi ini. Mungkin seseorang memberi tahu Anda bahwa unit yang menguji metode pribadi salah. Tapi itu hanya berarti Anda mungkin tidak menyebutnya "unit test" tetapi "tes pribadi" atau apa pun yang Anda suka menyebutnya.
Bahasa Swift memecahkan masalah yang Anda tidak ingin mengekspos A, B, C sebagai metode publik hanya karena Anda ingin mengujinya dengan memberi fungsi atribut "dapat diuji". Kompiler memungkinkan metode yang dapat diuji secara pribadi dipanggil dari unit test, tetapi bukan dari kode non-test.
sumber
Ya, Anda gila .... SEPERTI FOX!
Ada beberapa cara untuk menguji metode pribadi, beberapa di antaranya tergantung pada bahasa.
Secara keseluruhan, jika Anda ingin menguji metode pribadi, Anda mungkin ingin memindahkannya ke metode publik pada ketergantungan dan menguji / menyuntikkan itu.
sumber
Tetap pragmatis. Menguji kasus khusus dalam metode pribadi dengan cara mengatur keadaan instance dan parameter ke metode publik sehingga kasus-kasus tersebut terjadi di sana, seringkali jauh terlalu rumit.
Saya menambahkan
internal
accessor tambahan (bersama-sama dengan benderaInternalsVisibleTo
rakitan pengujian), dengan nama yang jelasDoSomethingForTesting(parameters)
, untuk menguji metode "pribadi" tersebut.Tentu saja, implementasinya dapat berubah kapan saja, dan tes-tes tersebut termasuk pengakses tes menjadi usang. Itu masih lebih baik daripada kasus yang belum diuji atau tes yang tidak dapat dibaca.
sumber