Apakah menambahkan tes unit masuk akal untuk kode lawas yang terkenal?

21
  • Saya sedang berbicara tentang unit test dalam arti TDD. (Bukan "integrasi" otomatis, atau apa yang Anda sebut pengujian.)
  • Kode lawas seperti pada kode: (C ++) tanpa tes. (lihat: Michael Feathers Bekerja Secara Efektif dengan Legacy Code )
  • Tetapi juga kode warisan seperti dalam: Kode yang tim kami telah kerjakan selama 10-5 tahun terakhir, jadi kami sangat sering memiliki ide yang bagus tentang di mana harus meletakkan sesuatu untuk mengubah sesuatu.
  • Kami memang memiliki tes unit di tempat (melalui Boost.Test) untuk beberapa modul yang datang kemudian atau telah menjadi "alami" cocok untuk tes unit (wadah aplikasi khusus, string-stuff, pembantu jaringan, dll.)
  • Kami belum memiliki tes penerimaan otomatis yang tepat.

Sekarang, baru-baru ini saya memiliki "kesenangan" untuk mengimplementasikan 3 fitur baru yang menghadap pengguna.

Masing-masing membutuhkan sekitar 1-2 jam untuk mempercepat dengan bagian-bagian kode yang perlu saya ubah, 1-2 jam untuk menerapkan kode (kecil) yang perlu saya ubah dan 1-2 jam lagi untuk memastikan aplikasi berlari dengan benar setelah itu dan lakukan apa yang seharusnya dilakukan.

Sekarang, saya benar-benar menambahkan kode kecil. (Saya pikir satu metode dan beberapa saluran panggilan untuk setiap fitur.)

Memfaktorkan kode ini (melalui salah satu metode yang disarankan dalam WEwLC ), sehingga tes unit akan masuk akal (dan bukan tautologi lengkap) akan dengan mudah dilakukan 2-4 jam lagi, jika tidak lebih. Ini akan menambah waktu 50% -100% untuk setiap fitur, tanpa manfaat langsung, seperti

  1. Saya tidak memerlukan unit test untuk memahami apa pun tentang kode
  2. Pengujian manual adalah jumlah pekerjaan yang sama, karena saya masih perlu menguji apakah kode diintegrasikan dengan benar ke seluruh aplikasi.

Memang, jika , di kemudian hari, "seseorang" datang dan menyentuh kode itu, secara teoritis dia bisa mendapat manfaat dari unit test itu. (Hanya secara teoritis, pulau kode yang diuji akan hidup di lautan kode yang tidak diuji.)

Jadi, "kali ini" saya memilih untuk tidak melakukan kerja keras menambahkan unit test: Perubahan kode untuk mendapatkan hal-hal yang sedang diuji akan jauh lebih kompleks daripada perubahan kode untuk mendapatkan fitur dengan benar (dan bersih) diimplementasikan.

Apakah ini sesuatu yang khas untuk kode lawas yang digabungkan? Apakah saya malas / apakah kita menetapkan prioritas yang salah sebagai sebuah tim? Atau apakah saya bijaksana, hanya menguji hal-hal di mana overhead tidak terlalu tinggi?

Martin Ba
sumber
bagaimana jika beberapa departemen lain akan mengambil alih "kode warisan terkenal" Anda? Apa yang akan dilakukan orang-orang di sana?
Alex Theodoridis

Jawaban:

18

Anda harus pragmatis tentang situasi ini. Semuanya harus memiliki nilai bisnis, tetapi bisnis harus memercayai Anda untuk menilai apa nilai pekerjaan teknis itu. Ya, selalu ada manfaatnya memiliki unit test, tetapi apakah manfaat itu cukup besar untuk membenarkan waktu yang dihabiskan?

Saya selalu berdebat tentang kode baru tetapi, pada kode warisan, Anda harus membuat keputusan penilaian.

Apakah Anda sering berada di area kode ini? Lalu ada kasus untuk perbaikan terus-menerus. Apakah Anda membuat perubahan signifikan? Lalu ada kasus bahwa itu sudah kode baru. Tetapi jika Anda membuat kode satu baris di area kompleks yang mungkin tidak akan disentuh lagi selama setahun, tentu saja biaya (belum lagi risiko) rekayasa ulang terlalu besar. Hanya menampar satu baris kode Anda di sana dan pergi mandi cepat.

Rule of thumb: Selalu berpikir untuk diri sendiri, " Apakah saya percaya bahwa bisnis mendapat manfaat lebih dari pekerjaan teknis yang saya rasa harus saya lakukan daripada pekerjaan yang mereka minta yang akan ditunda sebagai hasilnya? "

pdr
sumber
Apa kode yang baik? Satu yang dirancang dengan baik, diuji, didokumentasikan, dan bukti di masa depan atau yang Anda dibayar? Seperti biasa: Anda bisa mendapatkannya dengan baik ; Anda bisa memilikinya murah ; Anda dapat memilikinya dengan cepat . Pilih salah satu, yang ketiga adalah biaya Anda.
Sardathrion
2
"Saya selalu berdebat tentang kode baru" ... "kode baru" dalam basis kode lama atau "kode baru baru"? :-)
Martin Ba
pdr punya ide yang tepat. Ini adalah keputusan engineering (keputusan tradeoff). Umumnya jika Anda memiliki kode besar yang diperiksa, sebaiknya tinggalkan saja. Saya telah melihat upaya TDD pada kode lawas (hanya satu tahun, tapi itu sudah cukup) berakhir dengan biaya berbulan-bulan dan akhirnya menghabiskan uang dan merusak aplikasi warisan selama berbulan-bulan sampai bug yang diperkenalkan oleh refactor TDD diperbaiki. Jika kode / fitur dilakukan dan diuji, jangan rusak untuk menambahkan instrumentasi (TDD) untuk memberi tahu Anda sesuatu yang sudah Anda ketahui (bahwa itu berfungsi).
anon
10

Keuntungan dari unit test dalam pengertian TDD adalah mendapatkan sesuatu yang berdiri sendiri, tanpa perlu tradisi lisan yang dibangun selama bertahun-tahun oleh tim yang stabil.

Ini adalah keberuntungan besar bahwa tim yang sama telah mengerjakan proyek yang sama untuk waktu yang lama. Tapi ini akhirnya akan berubah. Orang sakit, bosan, atau dipromosikan. Mereka bergerak, pensiun atau mati. Yang baru datang dengan ide-ide baru dan keinginan untuk memperbaiki segala sesuatu dengan cara yang mereka pelajari di sekolah. Perusahaan dijual dan dibeli. Kebijakan manajemen berubah.

Jika Anda ingin proyek Anda bertahan, Anda harus mempersiapkannya untuk perubahan.

mouviciel
sumber
3

Tes unit penulisan adalah bukti masa depan kode Anda. Jika basis kode tidak memiliki tes, maka Anda harus menambahkan tes baru untuk semua fitur baru karena itu membuat kode sedikit lebih kuat.

Saya menemukan bahwa menambahkan tes, bahkan dalam kode lama, bermanfaat dalam jangka menengah dan panjang. Jika perusahaan Anda tidak peduli dengan jangka menengah dan panjang, saya akan mencari perusahaan lain. Sebagai tambahan, saya tidak berpikir bahwa dibutuhkan lebih lama untuk menguji secara manual daripada yang dibutuhkan untuk menulis uji unit yang ditetapkan. Jika ya, maka Anda perlu berlatih kode kata yang difokuskan pada tes menulis.

Sardathrion - Pasang kembali Monica
sumber
1
Tapi, tapi, tapi! :-) Itu sedikit harus diterjemahkan ke peningkatan 100% dalam waktu yang dibutuhkan untuk mengimplementasikan fitur baru. Itu tidak mengurangi waktu yang dibutuhkan untuk mengimplementasikan fitur-fitur selanjutnya. Ini dapat mengurangi waktu yang dibutuhkan saat mengganti barang.
Martin Ba
3
Anda memastikan bahwa perubahan di area kode tidak memperkenalkan bug baru, bahwa pengguna baru (yang kurang berpengalaman) dapat memperoleh pemahaman yang jelas tentang kode, dan bahwa efek samping yang mempengaruhi area tersebut adalah batuk pada waktu pengujian alih-alih saat dirilis. waktu. Pengujian membantu memverifikasi bahwa kode melakukan apa yang seharusnya tidak membuatnya lebih mudah untuk menambahkan fitur nanti. Saya menemukan bahwa menambahkan tes, bahkan dalam kode lama, bermanfaat dalam jangka menengah dan panjang . Jika perusahaan Anda tidak peduli dengan jangka menengah dan panjang, saya akan mencari perusahaan lain.
Sardathrion
1
@ Martin karena jelas apa yang Anda lakukan adalah kode apa yang Anda pikirkan tentang fitur tersebut, dan kemudian mengirimkannya. Tidak ada pengujian yang dilakukan sama sekali pada tahap apa pun ... tidak, tunggu. Sebagai pengembang, kita semua menguji kode kita (setidaknya dengan tangan) sebelum mengatakan itu selesai. Mengganti "dengan tangan" dengan "dengan menulis tes otomatis" bukan peningkatan waktu 100%. Seringkali, saya menemukan ini tentang waktu yang sama diambil.
Kaz Dragon
1
@Kaz - "Mengganti" dengan tangan "dengan" dengan menulis tes otomatis "bukan peningkatan waktu 100%. Seringkali, saya merasakan waktu yang hampir bersamaan." - YMMV, tapi untuk basis kode saya, ini jelas salah (seperti yang dijelaskan dalam pertanyaan).
Martin Ba
3
@ Ka: Maksud saya :-) maksudnya adalah: Tes unit menguji kode saya secara terpisah. Jika saya tidak menulis unit test saya tidak menguji kode secara terpisah, tetapi hanya jika kode tersebut dipanggil dengan benar dan menghasilkan hasil yang diinginkan dalam aplikasi. Dua poin ini (disebut dengan benar dan app-do-what-it-should) saya tetap harus menguji (secara manual) dan tidak dicakup oleh unit test. Dan unit test tidak akan mencakup dua poin ini tetapi akan "hanya" menguji fungsi saya secara terpisah. (Dan unit-test-testing ini akan menjadi tambahan dan tidak akan diimbangi oleh apa pun sejauh yang saya bisa lihat.)
Martin Ba
2

Tentu saja praktik terbaik menentukan Anda harus menguji unit kode apa pun yang Anda ubah. Namun pengkodean dunia nyata melibatkan banyak kompromi, waktu dan materi yang terbatas.

Yang perlu Anda lakukan adalah mengevaluasi biaya dalam hal memperbaiki bug dan membuat modifikasi tanpa tes unit. Anda kemudian dapat menilai terhadap investasi dalam menciptakan tes tersebut. Unit test sangat mengurangi biaya pekerjaan di masa depan tetapi harganya harus dibayar sekarang.

Intinya adalah jika sistem Anda jarang diubah maka mungkin tidak layak untuk menulis unit test tetapi jika itu dapat berubah secara berkala maka itu akan sia-sia.

Tom Squires
sumber
1

Semua keputusan rasional kecil ini untuk tidak membuat tes sedang membangun hutang teknis yang melumpuhkan yang akan kembali menghantui Anda ketika seseorang pergi & karyawan baru harus masuk & meningkat dengan cepat.

Ya, mungkin perlu 2-3 jam lagi untuk menulis unit test tetapi jika kode dikirim kembali dari pengujian Anda harus menguji semuanya secara manual lagi, dan mendokumentasikan pengujian Anda, lagi - Anda melakukannya bukan? Kalau tidak, bagaimana orang tahu apa yang Anda uji dan nilai apa yang Anda gunakan?

Tes unit mendokumentasikan perilaku kode yang diharapkan dari data uji yang digunakan untuk memeriksa fungsionalitas dan memberikan keyakinan baru yang wajar kepada pembuat kode bahwa mereka belum merusak sesuatu ketika membuat perubahan.

Harganya beberapa jam hari ini lebih dari pengujian manual tetapi kemudian Anda menguji setiap kali Anda melakukan perubahan menghemat waktu selama masa pakai kode.

Namun, jika Anda tahu bahwa kode tersebut akan dihentikan dalam beberapa tahun, saya sudah mengatakan perubahan karena Anda tidak akan selesai memasukkan tes dalam kode & itu tidak akan pernah membayar kembali.

mcottle
sumber
"dan dokumentasikan pengujianmu, lagi - kamu melakukannya bukan?" - {Menempatkan topi sinis:} Tentu saja tidak. Kami tidak berada di tanah peri pengembang. Hal-hal diimplementasikan, diuji, dan dikirim. Kemudian itu rusak dan diperbaiki dan diuji dan dikirim.
Martin Ba
Saya berharap bahwa semuanya akan diuji secara manual terlepas dari jumlah unit test. Tes penerimaan otomatis adalah masalah lain sepenuhnya. Tapi kemudian tes penerimaan tidak menjadi lebih sulit dengan basis kode menjadi warisan, jadi di luar ruang lingkup di sini.
pdr
2
mcottle - Anda kehilangan poin vital . Pengujian unit tidak akan mengurangi waktu yang dibutuhkan untuk melakukan "pengujian fungsionalitas manual" dari fitur yang sudah selesai. Saya masih harus mengklik-melalui semua dialog yang terlibat dengan subset yang bijaksana dari input yang mungkin untuk memastikan aplikasi selesai sebenarnya sebagai dibangun melakukan apa yang seharusnya dilakukan. (Saya akui bahwa pengujian unit secara teoritis dapat membantu membatasi siklus tes manual ini hanya satu putaran jika pengujian unit memastikan bahwa saya tidak akan menemukan masalah yang jelas hanya selama pengujian manual.)
Martin Ba
0

Nilai unit test tidak hanya terletak pada pengujian fitur baru ketika itu dikembangkan. Manfaat unit test diperoleh sebagian besar di masa depan.

Ya, Anda mungkin harus menghabiskan waktu yang kelihatannya terlalu banyak untuk membuat kode warisan Anda dapat diuji.

Tetapi jika tidak, Anda akan, atau tentu saja , harus menghabiskan banyak waktu, lebih banyak, lebih banyak menguji fitur ini. Tidak hanya pada pengembangan awalnya, tetapi dengan setiap versi baru dari perangkat lunak Anda. Tanpa unit yang menguji Anda, dan bentuk pengujian otomatis lainnya, Anda tidak memiliki pilihan lain selain menghabiskan berjam-jam pengujian manual untuk memastikan bahwa fitur Anda tidak secara tidak sengaja rusak, bahkan ketika fitur itu sendiri tidak diubah.

Marjan Venema
sumber
1
"Tanpa tes unit Anda tidak memiliki cara lain untuk memastikan bahwa fitur Anda tidak secara tidak sengaja rusak, bahkan ketika fitur itu sendiri tidak diubah." - Tes unit tidak akan membantu. Untuk memastikannya , saya harus memiliki tes integrasi / penerimaan otomatis.
Martin Ba
Ya, tes unit hanyalah langkah pertama. Jawaban yang diedit untuk menjelaskan
Marjan Venema