Kadang-kadang fungsi pribadi dari suatu modul atau kelas hanyalah unit fungsional internal internal yang belum diekstraksi, yang mungkin pantas untuk diuji sendiri. Jadi mengapa tidak mengujinya? Kami akan menulis tes untuk mereka nanti jika / ketika mereka diekstraksi. Jadi mengapa tidak menulis tes sekarang, ketika mereka masih bagian dari file yang sama?
Untuk menunjukkan:
Pertama, saya menulis module_a
. Sekarang saya ingin menulis tes untuk itu. Saya ingin menguji fungsi 'pribadi' _private_func
. Saya tidak mengerti mengapa saya tidak akan menulis tes untuk itu, jika nanti saya mungkin refactor ke modul internalnya sendiri, dan kemudian menulis tes untuk itu.
Misalkan saya memiliki modul dengan fungsi-fungsi berikut (bisa juga kelas):
def public_func(a):
b = _do_stuff(a)
return _do_more_stuff(b)
_do_stuff
dan _do_more_stuff
merupakan fungsi 'pribadi' dari modul.
Saya memahami gagasan bahwa kita hanya harus menguji antarmuka publik, bukan detail implementasi. Namun, ada satu hal:
_do_stuff
dan _do_more_stuff
berisi sebagian besar fungsi modul. Masing-masing dari mereka bisa menjadi fungsi publik dari modul 'internal' yang berbeda. Tetapi mereka belum berevolusi dan cukup besar untuk diekstraksi ke file yang terpisah.
Jadi menguji fungsi-fungsi ini terasa benar karena mereka adalah unit fungsionalitas yang penting. Jika mereka berada di modul yang berbeda sebagai fungsi publik, kami akan mengujinya. Jadi mengapa tidak menguji mereka ketika mereka belum (atau pernah) diekstraksi ke file yang berbeda?
Jawaban:
Kebutuhan untuk menguji tidak sama dengan kebutuhan untuk umum.
Kode non trivial membutuhkan pengujian terlepas dari paparan. Perilaku non publik tidak perlu ada apalagi diuji.
Pandangan yang bertentangan ini dapat membuat Anda ingin membuat setiap fungsi menjadi publik atau menolak untuk memfaktorkan kode ke dalam suatu fungsi kecuali itu akan menjadi publik.
Ini bukan jawabannya. Bersedia membuat fungsi pembantu pribadi. Uji mereka melalui antarmuka publik yang menggunakannya sebanyak mungkin.
Jika pengujian melalui antarmuka publik tidak menggunakan fungsi privat, fungsi privat akan mencoba untuk memperbolehkannya.
Validasi dapat membantu mempersempit fungsi privat yang dimungkinkan. Jika Anda tidak bisa melewati nol melalui antarmuka publik, Anda masih bisa melempar pengecualian jika tetap ada.
Kenapa harus kamu? Mengapa menguji apa yang tidak akan pernah Anda lihat? Karena semuanya berubah. Mungkin bersifat pribadi sekarang, tetapi bersifat publik nanti. Kode panggilan bisa berubah. Kode yang secara eksplisit menolak null membuat penggunaan yang tepat dan status yang diharapkan menjadi jelas.
Tentu saja nol bisa baik-baik saja. Ini hanya contoh di sini. Tetapi jika Anda mengharapkan sesuatu, itu berguna untuk membuat harapan itu jelas.
Itu mungkin bukan jenis pengujian yang ada dalam pikiran Anda, tetapi mudah-mudahan Anda akan bersedia untuk membuat fungsi pembantu pribadi saat yang tepat.
Keinginan untuk menguji itu baik, tetapi itu tidak seharusnya menjadi kekuatan pendorong dalam desain API publik Anda. Rancang API publik agar mudah digunakan. Kemungkinan tidak akan terjadi jika setiap fungsi bersifat publik. API harus menjadi sesuatu yang orang bisa mengerti cara menggunakan tanpa masuk ke dalam kode. Jangan biarkan orang-orang seperti itu bertanya-tanya untuk apa fungsi pembantu aneh ini.
Menyembunyikan fungsi pembantu publik dalam modul internal adalah upaya untuk menghormati kebutuhan akan API yang bersih sambil mengekspos para pembantu untuk pengujian. Saya tidak akan mengatakan ini salah. Anda mungkin mengambil langkah pertama menuju lapisan arsitektur yang berbeda. Tapi tolong, kuasai seni menguji fungsi pembantu pribadi melalui fungsi publik yang menggunakannya terlebih dahulu. Dengan begitu Anda tidak akan terlalu menggunakan solusi ini.
sumber
Jawaban singkat: Tidak
Jawaban yang lebih panjang: Ya, tetapi melalui 'API' publik kelas Anda
Seluruh gagasan anggota pribadi suatu kelas adalah bahwa mereka mewakili fungsionalitas yang seharusnya tidak terlihat di luar 'unit' kode, betapapun besar Anda ingin mendefinisikan unit itu menjadi. Dalam kode berorientasi objek bahwa unit sering berakhir menjadi kelas.
Anda harus membuat kelas Anda dirancang sedemikian rupa sehingga dimungkinkan untuk memanggil semua fungsi pribadi melalui berbagai kombinasi keadaan input. Jika Anda menemukan tidak ada cara yang relatif lurus ke depan untuk melakukan ini, itu mungkin mengisyaratkan bahwa desain Anda perlu perhatian lebih dekat.
Setelah klarifikasi pertanyaan, ini hanya soal semantik. Jika kode tersebut dapat beroperasi sebagai unit mandiri yang terpisah, dan sedang diuji seolah-olah itu adalah kode publik, saya tidak dapat melihat manfaat dari tidak memindahkannya ke modul mandiri. Saat ini, ini hanya membingungkan para pengembang di masa depan (termasuk diri Anda, dalam waktu 6 bulan), mengapa kode publik yang tampak tersembunyi di dalam modul lain.
sumber
Inti dari fungsi pribadi adalah bahwa mereka adalah detail implementasi tersembunyi yang dapat diubah sesuka hati, tanpa mengubah API publik. Untuk kode contoh Anda:
Jika Anda memiliki serangkaian tes yang hanya digunakan
public_func
, maka jika Anda menulis ulang untuk:kemudian, selama hasil pengembalian untuk nilai tertentu
a
tetap sama, maka semua tes Anda akan baik. Jika hasil pengembalian berubah, tes akan gagal, menyoroti fakta bahwa ada sesuatu yang rusak.Ini semua adalah hal yang baik: API publik statis; pekerjaan batin yang dikemas dengan baik; dan tes yang kuat.
Namun, jika Anda akan menulis tes untuk
_do_stuff
atau_do_more_stuff
kemudian membuat perubahan di atas, Anda sekarang akan memiliki banyak tes yang rusak, bukan karena fungsi berubah, tetapi karena implementasi fungsi itu berubah. Tes-tes itu perlu ditulis ulang agar berfungsi dengan fungsi-fungsi baru, tetapi setelah membuatnya berfungsi, yang Anda tahu hanyalah bahwa tes-tes itu bekerja dengan fungsi-fungsi baru. Anda akan kehilangan tes asli dan tidak akan tahu apakah perilakupublic_func
telah berubah dan tes Anda pada dasarnya tidak akan berguna.Ini adalah hal yang buruk: API yang berubah; pekerjaan dalam yang terbuka dengan erat digabungkan dengan tes; dan uji rapuh yang berubah segera setelah perubahan implementasi dilakukan.
Jadi tidak, jangan menguji fungsi pribadi. Pernah.
sumber