Bagaimana cara menulis unit test untuk kode lawas (yang saya tidak mengerti)?

8

Meneruskan

Saya sudah membaca banyak hal sebelum mengajukan pertanyaan ini, termasuk banyak pertanyaan yang relevan di sini di SE:

Namun, saya merasa gatal belum tergores setelah membaca untuk bantuan.


TL; DR

Bagaimana cara menulis unit test untuk kode lawas yang tidak dapat saya jalankan, simulasi, baca, atau mudah dimengerti? Tes regresi apa yang berguna untuk komponen yang mungkin berfungsi seperti yang dimaksudkan?


Keseluruhan gambar

Saya magang musim panas yang kembali lagi saat saya beralih ke sekolah pascasarjana. Penugasan saya melibatkan persyaratan ini:

  1. Untuk produk tertentu, evaluasi apakah tim perangkat lunak kami dapat meningkatkan versi IDE dan JUnit mereka tanpa kehilangan kompatibilitas dengan proyek yang ada.
  2. Kembangkan tes unit untuk beberapa komponen dalam kode Java yang ada (sebagian besar bukan Java). Kami ingin meyakinkan tim perangkat lunak bahwa pengujian unit dan TDD adalah alat yang sangat berharga yang harus mereka gunakan. (Saat ini ada cakupan kode 0%.)
  3. Entah bagaimana, akhiri hari-hari pengkodean koboi untuk sistem kritis.

Setelah mendapatkan salinan kode sumber, saya mencoba membangun dan menjalankannya, sehingga saya bisa mengerti apa yang dilakukan produk ini dan bagaimana cara kerjanya. Saya tidak bisa. Saya bertanya kepada penyelia saya bagaimana saya melakukannya, dan saya diberi mesin mandiri baru yang mampu membangunnya, termasuk skrip pembuatan yang sebenarnya. Itu tidak berhasil karena seperti yang seharusnya, kode produksi mereka hanya berjalan pada sistem embedded yang dirancang untuknya. Namun, mereka memiliki simulator untuk tujuan ini, jadi mereka memperoleh simulator dan menaruhnya di mesin ini untuk saya. Simulator juga tidak berfungsi. Sebagai gantinya, saya akhirnya menerima cetakan GUI untuk layar tertentu. Mereka juga tidak memiliki komentar kode di mana pun dalam 700.000+ Java LOC, membuatnya semakin sulit untuk dipahami. Selanjutnya, ada masalah yang mengevaluasi apakah proyek mereka kompatibel dengan IDE yang lebih baru atau tidak. Khususnya, kode mereka tidak dimuat dengan benar ke dalam versi IDE yang mereka gunakan.

Inventaris saya terlihat seperti ini:

  • NetBeans 8, 9, 10, 11
  • JUnit 4, 5
  • Kode sumber mereka untuk produk tertentu (termasuk 700.000+ Java LOC)
  • Hampir tidak ada komentar kode (terkadang tanda tangan)
  • Tidak ada tes yang ada
  • Foto fisik jendela GUI
  • Dokumen desain perangkat lunak (109 hal.) Yang tidak membahas komponen dalam gambar

Saya setidaknya memiliki cukup untuk secara teoritis menulis tes yang dapat dijalankan. Jadi, saya mencoba unit test dasar pada komponen ini. Namun, saya tidak bisa menginisialisasi objek yang ia miliki sebagai dependensi, yang mencakup model, manajer, dan koneksi DB. Saya tidak memiliki banyak pengalaman JUnit di luar pengujian unit dasar, jadi ikuti saya ke bagian selanjutnya.


Apa yang Saya Pelajari dari Membaca Saya

  1. Mengolok-olok: Jika saya menulis unit test, kemungkinan perlu memiliki variabel tiruan untuk dependensi produksi yang saya tidak dapat dengan mudah menginisialisasi setUp.
  2. Semua orang di sini dengan bebas menyarankan buku "Bekerja Efektif dengan Kode Legacy" oleh Michael Feathers.
  3. Tes regresi mungkin merupakan tempat yang baik untuk memulai. Saya tidak berpikir saya memiliki cukup senjata untuk mencoba pengujian integrasi, dan tes regresi akan memberikan kepuasan lebih instan kepada tim perangkat lunak kami. Namun, saya tidak memiliki akses ke bug yang dikenal; tapi, aku mungkin bisa bertanya.

Dan sekarang upaya untuk mengartikulasikan ketidakpastian yang masih saya miliki sebagai pertanyaan. Pada dasarnya, saya tidak mengerti bagaimana bagian menulis tes ini. Dengan asumsi saya tidak menerima panduan lebih lanjut dari penyelia saya (kemungkinan), ada di ballpark saya untuk tidak hanya mempelajari apa yang komponen ini lakukan tetapi untuk memutuskan tes apa yang sebenarnya berguna sebagai tes regresi.

Sebagai profesional yang telah bekerja dengan proyek seperti ini lebih lama daripada saya, dapatkah Anda menawarkan panduan tentang cara menulis tes unit dalam situasi seperti ini?

Joshua Detwiler
sumber
12
How do I write unit tests for legacy code that I can't build, run, simulate, read about, or otherwise understand?- Kamu tidak bisa. Anda harus setidaknya tahu apa output yang diharapkan untuk input yang diberikan.
Robert Harvey
1
Sudahkah Anda membaca buku Michael Feathers?
Robert Harvey
@RobertHarvey Ini sedikit hiperbola. Jelas saya bisa meluangkan waktu untuk membaca kode untuk memahaminya, tetapi itu biasanya merupakan pilihan terakhir untuk sesuatu yang begitu besar. Dan tidak, saya belum melakukannya, karena saya baru menemukan buku pagi ini.
Joshua Detwiler
Jika Anda memiliki kode lawas yang bahkan tidak dapat Anda buat, apakah Anda yakin memiliki versi kode yang benar? Anda harus menyelesaikan ini terlebih dahulu sebelum khawatir tentang tes otomatis - apakah kode yang Anda coba buat sama dengan apa pun yang dijalankan pengguna Anda? Langkah pertama dalam semua ini jika Anda memiliki sistem yang sedang berjalan dan bekerja adalah mencoba memahaminya dari sudut pandang pengguna; dapat membantu untuk membaca dokumentasi pengguna dan mungkin melihat data pengguna jika mungkin untuk mencoba mencari tahu apa yang dilakukannya
Ben Cottrell
2
Jika data sensor sangat penting untuk dieksekusi, mengejek sensor (atau apa pun ketergantungan eksternal) tampaknya merupakan tempat yang baik untuk memulai.
JimmyJames

Jawaban:

10

Untuk perkiraan pertama, para pemangku kepentingan dari suite uji adalah pengembang / pengelola kode. Anda akan membutuhkan waktu mereka. Bersikeras ini.

Tanyakan kepada mereka tentang masalah yang mereka hadapi.
Tanyakan kepada mereka tentang bug yang mereka perbaiki baru-baru ini (dalam beberapa tahun terakhir, dengan asumsi ini adalah proyek yang sangat lambat).

Saya mendapat kesan bahwa Anda tidak mengharapkan mereka ramah terhadap pekerjaan Anda; mungkin kau benar. Tetapi saya tidak berpikir Anda dapat membangun sesuatu yang bermanfaat tanpa bantuan mereka.

Mereka akan memegang tangan Anda melalui penulisan tes pertama. Mungkin Anda akan menyeretnya, tetapi Anda akan berpegangan tangan.

Setelah Anda memiliki satu tes, semoga akan lebih jelas bagaimana menulis yang kedua. Jika Anda berhasil membangun hubungan apa pun, tentu akan lebih jelas.

ShapeOfMatter
sumber
Terima kasih atas jawabannya! Bisakah Anda juga melihat bagian kedua dari pertanyaan saya juga? Paruh pertama saya adalah duplikat dari beberapa pertanyaan yang saya tautkan, dan saya terutama tertarik pada bagian lain dari pertanyaan saya karena itu.
Joshua Detwiler
Saya tidak tahu seberapa membantu saya. Apakah Anda mengalami kesulitan memahami cara kerja kerangka uji? Apakah Anda bertanya-tanya apa yang harus diuji? Untuk itu, tes regresi adalah pilihan yang baik: Tes apa yang akan mencegah bug ini yang baru saja kami perbaiki agar tidak didorong, jika kami begitu waspada .
ShapeOfMatter
Itu lebih "Tes regresi apa yang berguna untuk komponen yang mungkin berfungsi sebagaimana dimaksud?" Seperti, jika saya membuat tes yang bermanfaat, apa gunanya menjadi sama sekali buta tentang apa yang berhasil, apa yang tidak, dan bagaimana cara kerjanya sama sekali? Saya ada dalam ruang hampa terpisah dari tim perangkat lunak dan orang-orang yang memberi saya tugas ini ada dalam ruang hampa terpisah dari kami berdua.
Joshua Detwiler
Saya masih yakin bahwa Anda harus bersikeras masuk ke ruangan yang sama dengan orang-orang yang menulis perangkat lunak, idealnya selama beberapa hari, dan mungkin lebih dari sekali. Saya dapat berhubungan dengan situasi kerja yang dipaksakan absurd, tetapi pada satu titik orang perlu mengambil risiko pekerjaan seseorang atau menerima bahwa Anda hanya seorang penghangat bangku, saya kira
ShapeOfMatter
Mengenai Pengujian Regresi: Secara konseptual tidak berbeda dari pengujian lain: Apa yang ingin saya lakukan (atau tidak dilakukan) program sebelum saya menyatakan kepada rekan kerja bahwa itu bekerja? Jika ada catatan fitur baru atau bug terbaru, itu adalah tempat yang bagus untuk memulai. Atau lihat saja dokumentasi yang Anda miliki dan pilih sesuatu yang terlihat dapat diuji. Java memiliki fungsi yang diketik, yang bagus. Jenis tanda tangan yang jelas dapat memberi tahu Anda banyak tentang apa yang diharapkan dari suatu fungsi (dan dapat dianggap sebagai semacam unit test itu sendiri). Memeriksa perilaku NULL / empty-string / max-int mungkin juga baik.
ShapeOfMatter
3

Saya akan berasumsi pada titik tertentu Anda bisa mendapatkan kode untuk setidaknya mengkompilasi. Jika Anda bahkan tidak bisa sejauh itu, Anda sedang dalam tugas bodoh.


Kurangnya persyaratan, spesifikasi, atau tangkapan layar yang tepat bukanlah pemblokir untuk tes penulisan. Selama Anda dapat membaca kode sumber, Anda dapat menulis tes.

Jika Anda diberi izin untuk memperbaiki basis kode untuk mengisolasi hal-hal seperti koneksi database di belakang antarmuka mereka sendiri, menjadi mungkin untuk menulis beberapa tes unit kotak hitam - pada dasarnya menulis tes untuk melemparkan beberapa input pada suatu metode dan menegaskan perilaku atau outputnya. Dapatkan tes yang mencakup setiap baris kode dalam satu metode dan kemudian minta salah satu anggota senior tim meninjau tes Anda.

Jika Anda tidak diberi izin untuk memperbaiki basis kode untuk menulis tes unit maka tes integrasi penuh atau tes otomatisasi UI adalah satu-satunya pilihan Anda. Bahkan kemudian, pengujian kotak hitam adalah strategi terbaik Anda - melemparkan beberapa input di UI dan lihat bagaimana reaksinya. Buat pernyataan Anda. Mintalah anggota senior tim meninjau tes Anda.

Pada titik tertentu Anda akan memiliki tes otomatis yang cukup sehingga Anda dapat mulai refactoring basis kode dengan percaya diri untuk memperkenalkan tes unit. Pengujian UI memastikan case penggunaan bisnis utama berfungsi, dan kemudian Anda dapat memperbaiki arsitektur yang kondusif untuk pengujian tingkat unit atau komponen.

Manfaat lain dari tes UI adalah bahwa Anda dapat membangun reputasi dengan tim Anda bahwa Anda memahami basis kode, yang pada gilirannya membuatnya lebih terbuka untuk Anda memperkenalkan perubahan, karena buktinya ada di puding. Dan Anda akan membuat puding dengan cara menulis tes kelulusan.

Pendeknya:

  • Tulis pengujian Black Box sebagai pengujian UI unit atau otomatis
  • Mintalah anggota senior meninjau tes Anda

Anda akan terkejut betapa cepatnya Anda dapat mempelajari tampilan gambar besar dari aplikasi 700.000 baris

Greg Burghardt
sumber
1

Berdasarkan uraian masalah dan komentar Anda, saya pikir yang terbaik yang dapat Anda lakukan adalah mulai dengan Java API dan mencoba membangun satu unit test di sekitar metode yang terisolasi.

Tanpa akses ke kode, saya hanya bisa memberi Anda panduan terbatas tetapi saya akan mencari sesuatu yang di dalamnya a) tidak memiliki dependensi b) tidak membuat perubahan keadaan. Sebagai contoh. katakanlah ada metode yang mengambil nilai dan memeriksa bahwa itu jatuh dalam kisaran yang diberikan. Jika Anda tidak dapat menemukan sesuatu tanpa dependensi, coba sesuatu yang mengambil nilai dari dependensi dan mencoba untuk mengejeknya.

Setelah Anda menemukan sesuatu yang kecil seperti ini, Anda dapat mulai membuat tes. Jika metode ini menguji nilai positif, maka berikan nilai negatif dan pastikan itu menangkapnya, dll. Masalahnya di sini adalah Anda mungkin tidak tahu pasti apa perilaku yang benar. Anda mungkin perlu meminta bantuan atau menggali melalui dokumentasi untuk itu.

Anda tidak mungkin terlalu jauh dengan ini. Kenyataannya adalah bahwa menulis kode sehingga dapat diuji unit adalah seni untuk dirinya sendiri. Kode yang tidak ditulis dengan ini dalam pikiran bisa sulit untuk mustahil untuk unit test.

Opsi lain yang mungkin lebih mudah diimplementasikan adalah pengujian kompatibilitas biner. Artinya, Anda menangkap input dan output dari suatu sistem dan kemudian untuk menguji, Anda memberi makan input yang sama dan membandingkan output. Ini tidak akan memberi tahu Anda apakah kode itu benar atau salah untuk memulainya, tetapi dapat membantu mendeteksi kesalahan regresi di mana segala sesuatu berubah secara tidak sengaja ketika membuat beberapa modifikasi lainnya. Anda harus dapat menjalankan seluruh aplikasi untuk mewujudkannya.

JimmyJames
sumber