Apa nilai dari menulis tes unit tambahan ketika re-factoring fungsi yang lebih besar menjadi fungsi yang lebih kecil?

8

Jika saya memiliki fungsi unit yang diuji :

def do_everything():
    # turn twizzles
    # push buttons
    # move mountain

Dan saya re-faktor menjadi beberapa unit yang lebih kecil:

def do_everything():
    turn_twizzles()
    push_buttons()
    move_mountain()

def turn_twizzles():
    # turn twizzles

def push_buttons():
    # push buttons

def move_mountain():
    # move mountain

Apakah saya membuang-buang waktu untuk menulis tes unit ekstra untuk unit yang lebih kecil?

Adam Terrey
sumber

Jawaban:

15

Saya menganggap Anda sudah memiliki unit test yang mencakup perilaku do_everything()? Jika Anda melanggar turn_twizzles()dll sebagai metode pribadi, maka Anda belum mengubah perilaku eksternal sehingga Anda tidak perlu mengubah tes apa pun.

Namun jika turn_twizzles()dipublikasikan, maka Anda telah memperkenalkan fungsi baru (seperti yang diamati dari luar kelas) sehingga akan sangat berharga untuk menguji ini.

JacquesB
sumber
2
Tidak yakin mengapa jawaban ini dibatalkan. Singkat, to the point dan 100% tepat dalam nasehatnya.
David Arno
Ini jawaban yang sangat jelas, terima kasih. Saya pikir masalahnya (kredit ke @amuel untuk menyebutkannya tinju) adalah masalah cuaca atau tidak antarmuka publik telah berubah.
Adam Terrey
Downvote karena ini tidak lengkap. Bahkan jika fungsi-fungsi baru itu bukan bagian dari API publik, tes menulis bisa sangat membantu. Katakan tes untuk do_everything () gagal: di mana kesalahannya? Jika Anda memiliki tes untuk ketiga sub-fungsi itu akan lebih mudah ditemukan. Itu manfaat dari menulis tes dan itu harus disebutkan di sini.
marstato
1
@marstato: Biasanya dianggap sebagai ide buruk untuk menggunakan metode pribadi, karena menggabungkan pengujian dengan detail implementasi.
JacquesB
@ JaxquesB Itu umumnya tidak buruk. Anda bisa mengatakan bahwa sesuatu yang lebih tepat daripada tes integrasi biasa terkait dengan detail implementasi. Tetapi Anda menulis tes itu karena mereka membantu Anda melacak bug, bukan karena mereka membantu Anda membuktikan fungsionalitas yang benar. Pengubah akses selalu subyektif. Kata privatekunci dalam bahasa pemrograman hanyalah salah satu dari banyak cara membatasi akses ke sepotong kode.
marstato
12

Tergantung. Lebih tepatnya, itu tergantung pada

  • kompleksitas fungsi aslinya (jika itu sangat kompleks, menguji setiap bagian dengan sendirinya akan membuahkan hasil)
  • kompleksitas fungsi yang lebih kecil (jika mereka adalah bagian yang kompleks sendiri, mengujinya secara individual akan menghasilkan tes yang lebih berbutir halus dan deteksi akar penyebab yang lebih tepat jika terjadi kerusakan)
  • tes unit yang ada (jika mereka sudah menghasilkan cakupan yang cukup untuk semua "bagian", maka mungkin kurang layak untuk menulis tes individual)
  • jika Anda ingin menjaga fungsi-fungsi yang lebih kecil "detail implementasi" dari fungsi aslinya, atau tidak (untuk yang sebelumnya, tes unit penulisan untuk fungsi yang lebih kecil akan menjadi kontraproduktif untuk tujuan ini).

Terutama ketika "fungsi yang lebih kecil" itu tidak sepele seperti pada contoh Anda, tetapi akan memiliki daftar parameter input yang lebih atau kurang kompleks, itu bisa menjadi sangat sulit untuk menghasilkan tes unit yang cukup untuk fungsi asli Anda untuk menjamin fungsi yang lebih kecil diuji. dengan semua kombinasi input "menarik". Itu akan menjadi tanda yang jelas untuk menulis unit test khusus untuk fungsi yang lebih kecil juga.

Jadi, tidak ada "ya" atau "tidak" yang jelas untuk pertanyaan ini, itu adalah trade-off yang harus Anda putuskan per kasus.

Doc Brown
sumber
6

Jika turn_twizzles,, push_buttonsdan move_mountainbersifat publik dan dipanggil oleh kode lain, maka saya pikir penting untuk melakukan refactor pengujian Anda untuk menguji fungsi-fungsi ini secara individual.

Sayangnya setelah refactor Anda Anda memiliki masalah: untuk menguji unit do_everythingAnda harus mampu untuk mengejek turn_twizzles, push_buttonsdan move_mountain. Menulis tes untuk do_everythingtanpa mengejek dependensi akan menjadi tes integrasi - tidak harus hal yang buruk tergantung pada rencana pengujian Anda, tetapi tidak akan ada banyak manfaat karena Anda sudah menguji tiga fungsi yang lebih kecil secara individual. Ini mungkin saat yang tepat bagi Anda untuk mendesain ulang komponen ini dan berkolaborasi dengan objek lain untuk melakukan semua pekerjaan do_everything.

Jika turn_twizzles,, push_buttonsdan move_mountaintidak dipanggil secara eksternal, mereka harus ditandai pribadi, dan saya tidak akan merekomendasikan untuk mengujinya secara terpisah do_everything. Ini karena dari sudut pandang berwawasan ke luar, do_everythingakan menjadi unit terkecil (karena yang lain tidak dapat diakses). Lihat juga jawaban ini tentang memecah metode menggunakan metode pribadi.

Samuel
sumber
4
Saya telah downvoted ini sebagai, " untuk menguji unit do_everythingAnda harus mampu untuk mengejek turn_twizzles, push_buttonsdan move_mountain... " tergantung pada definisi omong kosong "uji unit".
David Arno
1
@ Bersikap adil, Samuel mengakui hal itu dalam jawabannya. Semacam.
GnP
4

Tidak. Tes unit tambahan lebih tepat. Jika move_mountaingagal, maka satu tes akan gagal yang mengatakan dengan sangat spesifik apa yang salah.

Ketepatan itu mengurangi waktu debugging, yang sangat berharga. Juga, karena tes ini lebih fokus, seharusnya lebih cepat dijalankan daripada menguji fungsi yang sama melalui fungsi penuh, memberikan umpan balik yang lebih cepat, yang berharga.

Telastyn
sumber