Praktik terbaik untuk retrofit kode lawas dengan tes otomatis

22

Saya akan mengambil tugas mengimplementasikan kembali antarmuka yang sudah didefinisikan (satu set file header C ++) dalam basis kode yang relatif besar dan lama. Sebelum melakukan ini, saya ingin memiliki cakupan tes selengkap mungkin, sehingga saya dapat mendeteksi kesalahan implementasi ulang sedini dan semudah mungkin. Masalahnya adalah bahwa basis kode yang sudah ada tidak dirancang agar mudah diuji, dengan (sangat) kelas besar dan fungsi, tingkat tinggi kopling, fungsi dengan (banyak) efek samping, dll.

Akan menyenangkan untuk mendengar pengalaman sebelumnya dengan tugas yang serupa, dan beberapa tips yang baik dan konkret tentang bagaimana Anda melakukan retrofit tes otomatis (unit, integrasi, regresi, dll.) Ke kode lawas Anda.

tjansson
sumber
1
Langkah 1: Cari Stack Overflow. Pertanyaan telah diajukan Banyak kali.
S.Lott

Jawaban:

20

Pertama-tama, dapatkan dan baca Bekerja Efektif dengan Kode Legacy oleh Michael Feathers - ini adalah bantuan yang sangat diperlukan untuk tugas-tugas tersebut.

Kemudian, beberapa catatan:

  • apakah Anda memiliki spesifikasi / kontrak yang tepat untuk antarmuka, atau apakah Anda praktis hanya memiliki implementasi yang ada sebagai "spesifikasi"? Dalam kasus sebelumnya lebih mudah untuk melakukan penulisan ulang lengkap dari awal, dalam yang terakhir sulit untuk mustahil.
  • jika Anda ingin mengimplementasikan kembali antarmuka, cara yang paling berguna untuk menghabiskan sumber daya pengujian Anda adalah dengan menulis tes hanya terhadap antarmuka. Tentu saja, ini tidak memenuhi syarat sebagai pengujian unit dalam arti yang ketat, melainkan pengujian fungsional / penerimaan, tetapi saya bukan purist :-) Namun, tes ini dapat digunakan kembali dan memungkinkan Anda untuk secara langsung membandingkan hasil dari dua implementasi secara berdampingan. .
  • secara keseluruhan, saya lebih suka refactoring kode yang ada daripada menulis ulang dari awal, kecuali itu benar-benar tidak dapat dipertahankan. (Tapi dalam kasus ini, bagaimana Anda akan menulis unit test menentangnya?) Periksa posting ini dari Joel untuk diskusi yang lebih rinci tentang masalah ini. Setelah membuat satu set tes penerimaan terhadap antarmuka memberi Anda jaring pengaman yang tipis namun bermanfaat, yang dengannya Anda dapat mulai dengan hati-hati refactoring kode yang ada agar unit dapat diuji (menggunakan ide-ide dari buku Feathers ').
Péter Török
sumber
Saya akan memberi ini +1 jika saya bisa. WELC adalah bacaan penting dan pasti akan digunakan untuk refactoring ...
Johnsyweb
Satu komentar kecil pada poin 2 adalah bahwa untuk sistem legacy, pengujian harus dilakukan sesuai dengan pola pikir tes karakterisasi . Yaitu, dengan setia menangkap perilaku perangkat lunak saat ini, dan menahan diri dari mengubah perilaku bahkan jika beberapa hasil pengujian tampak aneh atau tidak disetujui menurut pola pikir unit testing. (Btw ide ini juga berasal dari penulis WELC.)
rwong
@Rong, memang. Tanpa spesifikasi terperinci, atau pemilik produk yang berpengetahuan, tidak mungkin bagi pengembang untuk memutuskan apakah perilaku spesifik program a) disengaja dan diperlukan, b) tidak disengaja tetapi sekarang pengguna bergantung padanya, c) bug yang sebenarnya merugikan pengguna, d) bug yang sama sekali tidak diperhatikan sampai sekarang. Dalam dua kasus pertama, "memperbaiki" itu benar-benar akan merugikan pengguna, dan dalam kasus terakhir, perbaikan - meskipun secara teoritis benar - tidak akan memberikan manfaat yang terlihat.
Péter Török
4

Metode terbaik adalah tahu adalah Metode Mikado. http://mikadomethod.wordpress.com/2010/08/04/the-mikado-method-book/ Ini hanyalah generalisasi dari teknik sederhana, tetapi itu satu-satunya cara saya tahu untuk mulai meningkatkan kualitas kode dalam basis kode besar tanpa mengambil risiko yang tidak perlu.

WEWLC juga buku yang sangat bagus tentang itu tetapi ditulis dalam C ++ tidak selalu berguna dengan kode Java atau Ruby.

Uberto
sumber
2

Tes pas retro ke basis kode lama bisa sangat sulit jika desainnya monolitik.

Jika memungkinkan (apakah Anda punya waktu / uang), salah satu cara untuk maju adalah refactoring kode menjadi unit yang lebih dapat diuji.

ozz
sumber
1

Saya ingin menambahkan satu tautan . Ada beberapa contoh implementasi yang tidak begitu mudah diuji yang difaktorkan ulang menjadi kode yang lebih ramah xUnit. Sedangkan untuk pendekatan umum pergi coba tautan yang telah disebutkan (Joel post, Working With Legacy code

yoosiba
sumber