Apakah tes unit benar-benar bermanfaat? [Tutup]

98

Saya baru saja lulus dengan gelar CS dan saat ini saya memiliki pekerjaan sebagai Pengembang Junior .NET (C #, ASP.NET, dan formulir web). Kembali ketika saya masih di universitas, subjek pengujian unit memang dibahas tetapi saya tidak pernah benar-benar melihat manfaatnya. Saya mengerti apa yang seharusnya dilakukan, yaitu, menentukan apakah suatu blok kode cocok untuk digunakan atau tidak. Namun, saya belum pernah benar-benar harus menulis unit test sebelumnya, saya juga tidak pernah merasa perlu.

Seperti yang sudah saya sebutkan, saya biasanya mengembangkan dengan formulir web ASP.NET, dan baru-baru ini saya berpikir untuk menulis beberapa tes unit. Tapi saya punya beberapa pertanyaan tentang ini.

Saya pernah membaca bahwa pengujian unit sering terjadi melalui penulisan "ejekan". Walaupun saya memahami konsep ini, saya sepertinya tidak tahu bagaimana saya seharusnya menulis ejekan untuk situs web yang sepenuhnya dinamis, dan di mana hampir semuanya tergantung pada data yang berasal dari database. Sebagai contoh: Saya menggunakan banyak repeater yang memiliki peristiwa ItemDataBound dll. (Sekali lagi tergantung pada data yang "tidak dikenal").

Jadi pertanyaan nomor 1: Apakah tes unit penulisan untuk web ASP.NET membentuk sesuatu yang sering dilakukan, dan jika ya: bagaimana cara mengatasi masalah "lingkungan dinamis"?

Ketika saya berkembang saya mengalami banyak trial-and-error. Itu tidak berarti saya tidak tahu apa yang saya lakukan, tetapi maksud saya biasanya saya menulis beberapa kode, tekan Ctrl F5dan lihat apa yang terjadi. Sementara pendekatan ini melakukan pekerjaan sebagian besar waktu, kadang-kadang saya merasa bahwa saya menjadi sedikit tidak mengerti (karena pengalaman kecil saya). Terkadang saya membuang banyak waktu seperti ini juga.

Jadi, pertanyaan nomor 2: Apakah kalian menyarankan saya untuk mulai menulis tes unit? Saya pikir itu mungkin membantu saya dalam implementasi yang sebenarnya, tetapi sekali lagi saya merasa seperti itu mungkin memperlambat saya.

Jane Doe
sumber
1
Saya hanya ingin mengatakan sisi lain dari ini adalah beberapa tempat mengharuskan mereka sebagai latihan. Saya berada di suatu tempat sekarang karena kami tidak diizinkan untuk memeriksa kode kecuali dicakup dalam unit test. Jadi itu adalah hal yang perlu dicatat bahwa bahkan jika Anda mungkin tidak percaya pada mereka, Anda mungkin diminta untuk melakukannya di jalan. Saya pikir ini adalah keterampilan yang berguna untuk dipelajari dan dimiliki di gudang senjata Anda. Saya berkali-kali akan menemukan bug kecil dan kesalahan dalam kode saya dari melakukan tes, hampir satu sesi QA kecil dengan diri sendiri.
Adam
9
Bagaimana tepatnya Anda menutupi pengujian unit tanpa menulis pengujian unit? Apakah ini salah satu dari sekolah "nilai sendiri" atau "rancang kurikulum Anda sendiri"?
JeffO
4
Tes unit dipertanyakan - Bagus untuk bahasa dinamis, kurang bermanfaat semakin ketat bahasa Anda, tetapi LAKUKAN MEMBUAT TES. Mereka tidak harus menjadi unit test, tetapi Anda benar-benar harus memiliki tes integrasi yang dapat Anda jalankan dengan JUnit, itu sangat berguna.
Bill K
13
-1 Maaf, saya semua untuk argumen yang bagus, bahkan jika saya tidak setuju, tapi ini hanya salah. Tidak ada yang mengklaim "tes unit untuk menangkap bug dalam kode baru", jadi itu adalah uji coba - unit test adalah untuk menangkap regresi . Dan kutipan Dijkstra dikeluarkan dari konteks - konteksnya adalah pengujian tidak ada gunanya jika Anda memiliki spesifikasi formal untuk masalah Anda .
sleske
9
msgstr "unit test adalah untuk menangkap regresi". Tidak. Tes otomatis adalah untuk menangkap regresi. Regresi selalu membutuhkan pengujian yang sama untuk dijalankan ratusan kali sehingga sangat berharga untuk mengotomatiskannya. Sayangnya banyak tanggapan dan komentar pada pertanyaan ini benar-benar berurusan dengan masalah "Apakah tes otomatis sangat membantu?". Tes unit mungkin merupakan bentuk pengujian otomatis tetapi mereka memiliki fokus yang sama sekali berbeda. Saya tentu menganggap tes otomatis bernilai emas, tetapi itu tidak boleh digunakan sebagai argumen untuk membenarkan tes unit (atau TDD dalam hal ini).
njr101

Jawaban:

124

Menurut pendapat saya: ya mereka, dan ya Anda harus.

  1. Mereka memberi Anda kepercayaan diri pada perubahan yang Anda lakukan (semua yang lain masih berfungsi). Keyakinan ini adalah apa yang Anda butuhkan untuk mencetak kode, jika tidak, Anda mungkin takut untuk mengubah beberapa hal.

  2. Mereka membuat kode Anda lebih baik; sebagian besar kesalahan sederhana diketahui sejak awal dengan unit test. Menangkap bug lebih awal dan memperbaikinya selalu lebih murah daripada memperbaikinya nanti, misalnya ketika aplikasi sedang dalam produksi.

  3. Mereka berfungsi sebagai dokumentasi untuk pengembang lain tentang cara kerja kode Anda dan cara menggunakannya.

Masalah pertama yang Anda hadapi adalah bahwa ASP.NET sendiri tidak membantu Anda untuk menulis unit test - sebenarnya itu bekerja melawan Anda. Jika Anda punya pilihan, mulailah menggunakan ASP.NET MVC , yang dibuat dengan mempertimbangkan pengujian unit. Jika Anda tidak dapat menggunakan ASP.NET MVC, Anda harus menggunakan pola MVP di ASP.NET sehingga setidaknya Anda dapat menguji logika Anda dengan mudah.

Selain itu Anda hanya perlu mahir dalam menulis unit test. Jika Anda berlatih TDD, kode Anda dibuat dapat diuji — dengan kata lain, bagus dan bersih.

Saya akan menyarankan Anda untuk berlatih, dan memasangkan program. Saat membaca:

Atau, untuk ikhtisar pertama:

KeesDijk
sumber
4
Baru saja memulai pengujian unit saya harus setuju. Bukan hanya itu kebiasaan yang baik dan sangat berguna dikombinasikan dengan pendekatan TDD, tetapi juga meminimalkan banyak waktu. Saya tidak berpikir proyek saya bisa berguna jika saya tidak bisa hanya menjalankan tes unit dan memverifikasi bahwa semuanya berfungsi dengan baik bahkan setelah menambahkan fitur baru atau memperbaiki bug. Saya tidak bisa memikirkan melakukan pengujian regresi dengan cara lain.
kwelch
21
Jika unit-test berfungsi sebagai dokumentasi, ada sesuatu yang salah. Membaca 500 baris kode untuk memahami bagaimana 5 baris kode bekerja mundur.
Coder
4
@ Kode: ketika Anda menguji metode tingkat yang lebih tinggi, itu melibatkan lebih dari 5 baris kode.
7
@coder: dokumentasi kelas memberi tahu Anda layanan yang disediakan oleh instance kelas. Ini memberi tahu Anda lebih sedikit informasi tentang bagaimana instance kelas ini digunakan dalam konteks yang lebih besar, yaitu interaksi antara objek. Tes memberi Anda kode interaksi yang khas dalam beberapa kasus, yang telah berharga sebagai titik awal berkali-kali saya bahkan tidak bisa menghitungnya.
Stefano Borini
21
@ Kode: Ini tidak mendokumentasikan apa yang dilakukan kode, itu mendokumentasikan asumsi yang melekat dalam kode itu, yaitu mengapa dan kapan itu seharusnya bekerja. Jika asumsi yang mendasarinya tidak valid oleh perubahan ke SUT, satu atau lebih tes unit harus gagal. Ini tidak menggantikan dokumentasi desain / arsitektur tingkat tinggi, atau bahkan dokumen XML, tetapi mencakup apa yang tidak dapat dilakukan oleh hal-hal itu.
Aaronaught
95

Tidak.

Konsep di balik pengujian unit didasarkan pada premis yang telah diketahui salah sejak sebelum pengujian unit ditemukan: gagasan bahwa tes dapat membuktikan bahwa kode Anda benar.

Memiliki banyak tes yang semuanya lulus membuktikan satu dan hanya satu hal: bahwa Anda memiliki banyak tes yang semuanya lulus. Itu tidak membuktikan bahwa tes apa yang diuji cocok dengan spesifikasi. Itu tidak membuktikan bahwa kode Anda bebas dari kesalahan yang tidak pernah Anda pertimbangkan ketika Anda menulis tes. (Dan hal-hal yang Anda pikir untuk diuji adalah masalah yang mungkin Anda fokuskan, jadi Anda mungkin sudah mendapatkan yang benar!) Dan yang terakhir tapi tidak kalah pentingnya, itu tidak membuktikan bahwa tes, yang merupakan kode sendiri, bebas dari bug. (Ikuti yang terakhir sampai pada kesimpulan logisnya dan Anda berakhir dengan kura - kura sampai tuntas .)

Djikstra menghancurkan konsep tes-sebagai-bukti-kebenaran pada tahun 1988, dan apa yang ia tulis tetap sama validnya hari ini:

Sekarang sudah dua dekade sejak ditunjukkan bahwa pengujian program dapat secara meyakinkan menunjukkan keberadaan bug, tetapi tidak pernah dapat menunjukkan ketidakhadiran mereka. Setelah mengutip pernyataan yang dipublikasikan dengan baik ini, insinyur perangkat lunak kembali ke urutan hari dan terus memperbaiki strategi pengujiannya, seperti alkemis dahulu kala, yang terus menyempurnakan pemurnian chrysocosmic-nya.

Masalah lain dengan pengujian unit adalah bahwa hal itu menciptakan hubungan yang erat antara kode Anda dan suite pengujian. Ketika Anda mengubah kode, Anda akan mengharapkan beberapa bug muncul yang akan merusak beberapa tes. Tetapi jika Anda mengubah kode karena persyaratannya sendiri telah berubah, Anda akan mendapatkan banyak tes yang gagal, dan Anda harus memeriksa masing-masing secara manual dan memutuskan apakah tes tersebut masih valid atau tidak. (Dan itu juga mungkin, meskipun kurang umum, bahwa tes yang ada yang seharusnya tidak valid masih akan lulus karena Anda lupa mengubah sesuatu yang perlu diubah.)

Pengujian unit adalah yang terbaru dari garis mode perkembangan yang menjanjikan untuk membuatnya lebih mudah untuk menulis kode kerja tanpa benar-benar menjadi programmer yang baik. Tak satu pun dari mereka yang pernah berhasil menepati janji mereka, dan tidak juga yang ini. Tidak ada jalan pintas untuk benar-benar mengetahui cara menulis kode kerja .

Ada beberapa laporan pengujian otomatis yang benar-benar berguna dalam kasus di mana stabilitas dan keandalan sangat penting. Misalnya, proyek database SQLite. Tetapi apa yang diperlukan untuk mencapai tingkat keandalan mereka sangat tidak ekonomis untuk sebagian besar proyek: rasio kode uji-terhadap-aktual-SQLite hampir 1.200: 1. Sebagian besar proyek tidak mampu membayar itu, dan tetap tidak membutuhkannya.

Mason Wheeler
sumber
69
Itu membuktikan bahwa kode Anda berlaku dengan benar untuk tes-tes itu. Ini banyak yang aneh jika Anda bertanya kepada saya.
Stefano Borini
111
Siapa yang hari ini benar-benar percaya bahwa tes unit adalah "bukti kebenaran"? Tidak ada yang harus memikirkan itu. Anda benar bahwa mereka hanya membuktikan bahwa tes-tes tersebut lulus, tetapi itu satu poin data lebih banyak dari yang Anda miliki sebelum menulis tes unit. Anda perlu menguji di berbagai lapisan untuk memberi diri Anda wawasan tentang kualitas kode Anda. Tes unit tidak membuktikan kode Anda bebas dari cacat, tetapi mereka benar-benar meningkatkan kepercayaan diri Anda (atau seharusnya ...) bahwa kode melakukan apa yang Anda rancang untuk dilakukan, dan terus melakukan besok seperti yang dilakukan hari ini.
Bryan Oakley
40
> but if the test itself is buggy, then you have false confidencedan jika penguji manual tidak melakukan tugasnya dengan benar, Anda juga memiliki kepercayaan diri yang salah.
Stefano Borini
33
@MasonWheeler: maaf, Mason, saya tidak yakin. Dalam lebih dari beberapa dekade pemrograman saya tidak berpikir saya pernah melihat kasus di mana tes memberikan rasa aman yang salah. Mungkin beberapa dari mereka melakukannya dan kami memperbaikinya, tetapi biaya tes unit itu tidak sebanding dengan manfaat yang sangat besar dari memilikinya. Jika Anda dapat menulis kode tanpa mengujinya di tingkat unit, saya terkesan, tetapi sebagian besar programmer di luar sana tidak dapat melakukannya secara konsisten.
Bryan Oakley
41
Jika Anda menulis tes kereta yang kode Anda lulus, kode Anda kemungkinan juga kereta. Peluang menulis kode kereta dan tes kereta jauh lebih sedikit daripada kode kereta saja. Tes unit bukan obat mujarab. Mereka adalah lapisan ekstra yang baik (di mana bijaksana) untuk mengurangi beban pada penguji manual.
Telastyn
60

Jika Anda pernah melihat manfaat dari menulis metode utama untuk menguji beberapa kode kecil untuk sekolah, pengujian unit adalah versi profesional / perusahaan dari praktik yang sama.

Juga bayangkan overhead membangun kode, memulai server web lokal Anda, menjelajahi halaman yang dimaksud, memasukkan data atau mengatur input ke seed tes yang tepat, mengirimkan formulir, dan menganalisis hasilnya ... vs membangun dan memukul tombol jalankan nUnit.

Ini juga gambar yang menyenangkan ... masukkan deskripsi gambar di sini

Saya menemukan gambar ini di sini:
http://www.howtogeek.com/102420/geeks-versus-non-geeks-when-doing-repetitive-tasks-funny-chart/

Heath Lilley
sumber
2
Ya kamu bisa. Isolasikan layer web dalam pengujian unit Anda untuk menguji konfigurasi web (URL, validasi input, dll.). Dengan mematikan lapisan web dan basis data, Anda dapat menguji tingkat bisnis tanpa database atau server web. Saya menggunakan dbunit untuk menguji DB saya. Jika mau, Anda masih dapat melakukan pengujian integrasi penuh, tetapi saya melakukannya sebagai tugas khusus setelah pengembangan.
Heath Lilley
12
Grafis imut, tapi skalanya salah besar. Seperti yang saya tunjukkan dalam jawaban saya, cakupan uji penuh SQLite memerlukan sekitar 1200x lebih banyak kode dalam pengujian daripada kode aktual dalam produk itu sendiri. Dan bahkan jika Anda tidak yang obsesif tentang cakupan penuh, Anda masih perlu tes beberapa kali lebih dari produk bahkan mendekati setiap tingkat berguna cakupan dalam tes Anda. Agar akurat di sini, bagian vertikal dari garis merah itu harus terus naik dan naik dan naik sekitar 3 halaman.
Mason Wheeler
27
@MasonWheeler Itu kuda yang sangat bagus yang Anda kalahkan, saya pikir itu mungkin sudah mati ... SQLite memiliki banyak tes karena ini adalah basis data. Saya ingin memastikan itu berhasil. Sebagai contoh lain, kerangka kerja Silverstripe mendekati rasio tes: kode 1: 1, jadi SQLite tidak representatif.
Aatch
15
@MasonWheeler Anda gagal pada paradoks Zeno yang pertama . Jika Anda ingin memperbesar gambar ini ke tingkat pengujian SQLite, sumbu X juga harus memperluas sekitar 100 kali panjangnya saat ini.
Izkata
2
Ini terutama benar ketika Anda seorang pengembang backend yang tidak punya waktu untuk mulai membuat halaman web hitam dan putih hanya agar Anda dapat menguji logika back end Anda. Yang harus saya lakukan adalah menyediakan permintaan mock dan objek sesi dan menjalankan pengendali saya melalui tes unit, dan pada akhirnya semua saya tahu apakah itu benar atau salah. Jika Anda menggunakan DI, cukup menyuntikkan DAO yang berinteraksi dengan basis data dalam memori sehingga basis data Anda tidak berubah atau hanya melempar Exceptiondan menangkapnya sehingga data Anda tidak dikomit. Saya katakan YA ke unit testing.
Varun Achar
49

Unit testing memiliki sesuatu mistik tentang hal ini hari ini. Orang-orang memperlakukannya seolah-olah cakupan pengujian 100% adalah grail suci, dan seolah-olah pengujian unit adalah Satu Cara Sejati dalam mengembangkan perangkat lunak.

Mereka kehilangan intinya.

Pengujian unit bukanlah jawabannya. Pengujian adalah.

Sekarang, setiap kali diskusi ini muncul, seseorang (seringkali bahkan saya) akan mengeluarkan kutipan Dijkstra: "Pengujian program dapat menunjukkan keberadaan bug, tetapi tidak pernah menunjukkan ketidakhadiran mereka." Dijkstra benar: pengujian tidak cukup untuk membuktikan bahwa perangkat lunak berfungsi sebagaimana dimaksud. Tetapi itu perlu : pada tingkat tertentu, harus dimungkinkan untuk menunjukkan bahwa perangkat lunak melakukan apa yang Anda inginkan.

Banyak orang menguji dengan tangan. Bahkan penggemar TDD yang setia akan melakukan pengujian manual, meskipun mereka terkadang tidak mengakuinya. Tidak dapat dihindari: tepat sebelum Anda pergi ke ruang konferensi untuk mendemokan perangkat lunak Anda kepada klien / bos / investor / dll, Anda akan menjalankannya dengan tangan untuk memastikan itu akan bekerja. Tidak ada yang salah dengan itu, dan pada kenyataannya akan gila untuk hanya mengharapkan semuanya berjalan lancar tanpa menjalankannya secara manual - yaitu, mengujinya - bahkan jika Anda memiliki cakupan pengujian unit 100% dan kepercayaan penuh dalam pengujian Anda .

Tetapi pengujian manual, meskipun diperlukan untuk membangun perangkat lunak, jarang memadai . Mengapa? Karena pengujian manual itu membosankan, dan memakan waktu, dan dilakukan oleh manusia. Dan manusia terkenal buruk dalam melakukan tugas-tugas yang membosankan dan memakan waktu: mereka menghindari melakukannya kapan pun memungkinkan, dan mereka sering tidak melakukannya dengan baik ketika mereka dipaksa.

Mesin , di sisi lain, sangat baik dalam melakukan tugas-tugas yang membosankan dan memakan waktu. Lagi pula, untuk itulah komputer diciptakan.

Jadi pengujian sangat penting, dan pengujian otomatis adalah satu-satunya cara yang masuk akal untuk memastikan bahwa pengujian Anda dilakukan secara konsisten. Dan penting untuk menguji, dan menguji ulang, saat perangkat lunak dikembangkan. Jawaban lain di sini mencatat pentingnya pengujian regresi . Karena kompleksitas sistem perangkat lunak, perubahan yang tampaknya tidak berbahaya pada satu bagian sistem menyebabkan perubahan yang tidak disengaja (yaitu bug) di bagian lain sistem. Anda tidak dapat menemukan perubahan yang tidak disengaja ini tanpa suatu bentuk pengujian. Dan jika Anda ingin memiliki data yang dapat diandalkan tentang pengujian Anda, Anda harus melakukan pengujian secara sistematis, yang berarti Anda harus memiliki semacam sistem pengujian otomatis.

Apa hubungan semua ini dengan pengujian unit? Nah, karena sifatnya, unit test dijalankan oleh mesin, bukan oleh manusia. Oleh karena itu, banyak orang mendapat kesan salah bahwa pengujian otomatis sama dengan pengujian unit . Tapi itu tidak benar: tes unit hanya tes otomatis ekstra kecil .

Sekarang, apa nilainya dalam tes otomatis ekstra kecil ? Keuntungannya adalah mereka menguji komponen sistem perangkat lunak secara terpisah , yang memungkinkan penargetan pengujian yang lebih tepat , dan membantu dalam debugging . Tetapi pengujian unit tidak secara intrinsik berarti tes kualitas yang lebih tinggi . Ini sering mengarah pada tes kualitas yang lebih tinggi, karena itu mencakup perangkat lunak pada tingkat detail yang lebih baik. Tetapi adalah mungkin untuk sepenuhnya menguji perilaku hanya sistem yang lengkap, dan bukan bagian-bagian kompositnya, dan masih mengujinya secara menyeluruh.

Tetapi bahkan dengan cakupan uji unit 100%, sistem mungkin masih belum diuji secara menyeluruh. Karena masing-masing komponen dapat bekerja dengan sempurna dalam isolasi, namun tetap gagal ketika digunakan bersama-sama. Jadi pengujian unit, walaupun sangat bermanfaat, tidak cukup untuk memastikan bahwa perangkat lunak berfungsi seperti yang diharapkan. Memang, banyak pengembang melengkapi tes unit dengan tes integrasi otomatis, tes fungsional otomatis, dan pengujian manual.

Jika Anda tidak melihat nilai dalam unit test, mungkin cara terbaik untuk memulai adalah dengan menggunakan jenis tes otomatis yang berbeda. Dalam lingkungan web, menggunakan alat pengujian otomasi browser seperti Selenium akan sering memberikan kemenangan besar untuk investasi yang relatif kecil. Setelah mencelupkan jari-jari kaki ke dalam air, Anda akan lebih mudah melihat seberapa membantu pengujian otomatis. Dan begitu Anda memiliki tes otomatis, pengujian unit jauh lebih masuk akal, karena memberikan perputaran lebih cepat daripada integrasi besar atau tes ujung ke ujung, karena Anda dapat menargetkan tes hanya pada komponen yang sedang Anda kerjakan.

TL; DR: jangan khawatir tentang unit testing dulu. Hanya khawatir tentang pengujian perangkat lunak Anda terlebih dahulu.

Daniel Pryden
sumber
Unit test juga ditulis oleh manusia, dan bisa saja salah.
Seun Osewa
41

Tergantung

Ini adalah jawaban yang akan Anda lihat banyak mengenai pengembangan perangkat lunak, tetapi kegunaan uji unit sangat tergantung pada seberapa baik mereka ditulis. Sejumlah nominal unit test yang memeriksa fungsionalitas aplikasi untuk pengujian regresi bisa sangat berguna; Namun, sejumlah besar tes sederhana yang memeriksa pengembalian fungsi bisa sangat tidak berguna dan memberikan rasa aman yang salah karena aplikasi "memiliki banyak unit test."

Selain itu, waktu Anda sebagai pengembang sangat berharga dan waktu yang dihabiskan untuk menulis unit test adalah waktu yang tidak dihabiskan untuk menulis fitur baru. Sekali lagi, ini bukan untuk mengatakan Anda tidak harus menulis unit test, tetapi apakah setiap fungsi publik tunggal memerlukan unit test? Saya akan menyampaikan bahwa jawabannya adalah tidak. Apakah kode yang melakukan validasi input pengguna perlu pengujian unit? Sangat mungkin karena merupakan titik kegagalan umum dalam aplikasi.

Ini adalah salah satu area di mana pengalaman berperan, seiring waktu Anda akan mengenali bagian-bagian dari aplikasi yang dapat mengambil manfaat dari unit test, tetapi itu akan sementara sebelum Anda mencapai titik itu.

rjzii
sumber
Ini poin yang bagus. Anda harus tahu cara menulis tes yang bagus yang menangkap nilai SUT.
Andy
3
Ini pada dasarnya mencakup bagaimana saya diajarkan untuk melakukan tes unit - menulis tes untuk mencakup situasi yang paling penting / dapat dipecahkan terlebih dahulu, dan kemudian menambahkan lebih banyak tes ketika asumsi Anda ternyata salah (saya pikir ada sesuatu yang "tidak pernah gagal", tetapi ternyata berhasil) .
Brendan Long
38

Proyek yang dilakukan untuk kelas universitas sangat berbeda dari aplikasi bisnis yang akan Anda tulis di tempat kerja Anda. Perbedaannya adalah umur. Berapa lama proyek universitas "hidup"? Dalam kebanyakan kasus, ini dimulai ketika Anda menulis baris kode pertama dan berakhir ketika Anda mendapatkan nilai Anda. Anda bisa mengatakan itu, efektif itu hanya hidup untuk saat implementasi. "Rilis" biasanya sama dengan "kematian" nya.

Perangkat lunak yang dilakukan untuk bisnis melampaui titik rilis-kematian dari proyek universitas dan terus hidup selama bisnis membutuhkannya. Itu sangat panjang . Ketika berbicara tentang uang, tidak ada yang akan menghabiskan satu sen pun untuk memiliki "kode yang lebih dingin dan lebih rapi". Jika perangkat lunak yang ditulis dalam C 25 tahun yang lalu masih berfungsi dan cukup baik (sebagaimana dipahami oleh kebutuhan pemilik bisnisnya), diharapkan akan diminta untuk mempertahankannya (menambahkan fitur baru, meningkatkan yang lama - mengubah kode sumber ).

Kami sampai pada satu poin yang sangat penting - regresi . Di tempat saya bekerja kami memiliki dua tim yang mengelola dua aplikasi; satu, menulis sekitar 5-6 tahun yang lalu dengan cakupan tes kode yang sangat sedikit *, dan yang kedua, versi yang lebih baru dari aplikasi pertama dengan suite tes full-blown (unit, integrasi dan apa yang tidak). Kedua tim memiliki penguji manual (manusia). Ingin tahu berapa lama untuk memperkenalkan fitur baru yang cukup mendasar untuk tim pertama? 3 hingga 4 minggu. Setengah dari waktu ini adalah "memeriksa apakah semuanya masih berfungsi". Ini adalah waktu yang sibuk untuk penguji manual. Telepon berdering, orang-orang marah, ada yang rusak lagi. Tim kedua biasanya menangani masalah seperti itu dalam waktu kurang dari 3 hari.

Saya sama sekali tidak mengatakan bahwa unit test membuat kesalahan kode Anda rentan, benar atau kata-kata mewah lain yang dapat Anda buat. Baik mereka membuat bug menghilang secara ajaib. Tetapi ketika dikombinasikan dengan metode pengujian perangkat lunak otomatis lainnya, mereka membuat aplikasi Anda jauh lebih mudah dikelola daripada sebelumnya. Ini adalah kemenangan besar.

Dan yang tak kalah pentingnya, komentar oleh Brian yang menurut saya memukau seluruh masalah:

(...) mereka benar-benar meningkatkan kepercayaan diri Anda (atau harus ...) bahwa kode melakukan apa yang Anda rancang, dan terus melakukan besok apa yang dilakukannya hari ini.

Karena antara hari ini dan besok, seseorang mungkin membuat perubahan kecil yang akan menyebabkan kode generator laporan yang sangat penting macet. Tes mendorong peluang bahwa Anda akan menemukan ini sebelum pelanggan Anda sedikit membantu Anda.

* Mereka secara perlahan memperkenalkan lebih banyak dan lebih banyak tes ke basis kode mereka, tetapi kita semua tahu bagaimana hal ini biasanya terlihat.

km
sumber
10
+1000 untuk menautkan ke Software_Regression. Perguruan tinggi mengekspos unit test sebagai sesuatu yang harus Anda lakukan karena keyakinan semata, tanpa menjelaskan secara terperinci ada penyakit untuk dicegah dan dikendalikan dan bahwa penyakit itu disebut regresi . (maka ada masalah dengan tes regresi menjadi sesuatu yang sangat berbeda dari tes unit, untuk itu satu-satunya bacaan yang saya temukan menjelaskan dengan baik adalah sampel gratis dari buku ini )
ZJR
25

menulis unit test untuk ASP.NET webforms sesuatu yang sering dilakukan, dan jika itu adalah: bagaimana cara mengatasi masalah "lingkungan dinamis"?

Ini tidak sering dilakukan. Bekerja dengan elemen UI bukanlah tes unit yang baik, karena tidak ada cara yang bagus untuk memverifikasi secara terprogram bahwa hal-hal yang benar berakhir di layar di tempat yang tepat.

Apakah kalian menyarankan saya untuk mulai menulis tes unit? Saya pikir itu mungkin membantu saya dalam implementasi yang sebenarnya, tetapi sekali lagi saya merasa seperti itu mungkin memperlambat saya.

Di mana berlaku, ya. Mereka dapat sangat membantu dalam memverifikasi kasus-kasus tertentu secara berulang. Mereka membantu bertindak sebagai 'gesekan' terhadap perubahan yang menyusahkan, dan sebagai yang gagal aman ketika Anda membuat perubahan yang lebih baik.

Satu hal yang perlu diperhatikan adalah mereka biasanya akan memperlambat Anda.

Ini tidak apa-apa

Menghabiskan sedikit waktu sekarang akan (jika dilakukan dengan baik) menghemat waktu Anda di masa depan karena mereka menangkap beberapa bug, mencegah pengulangan beberapa bug, dan memungkinkan Anda untuk sedikit lebih nyaman melakukan perbaikan lain dalam kode agar tidak membusuk.

Telastyn
sumber
8
+1 untuk benar-benar menjawab kasus penggunaan pertanyaan! Semua orang melompat pada bagian "unit test" dan lupa tentang bagian "ASP.NET web form" ...
Izkata
1
Ini adalah jawaban yang bagus dan pantas mendapat lebih banyak upvotes, alasannya adalah karena Anda telah menjawab pertanyaan dan Anda jujur ​​dalam menilai memperlambat pengembang dan tidak menjanjikan bahwa setiap bug akan ditangkap atau dicegah, yang sepenuhnya dan sepenuhnya benar.
Mantorok
11

Saya baru saja lulus dengan gelar CS dan saat ini saya memiliki pekerjaan sebagai pengembang .NET junior (di C # dan biasanya ASP.NET, formulir web - bukan ASP.NET MVC). Kembali ketika saya masih di universitas, subjek pengujian unit mendapatkan perlindungan, tetapi saya tidak pernah benar-benar melihat manfaatnya.

Itu karena Anda tidak pernah memprogram besar.

Saya mengerti apa yang seharusnya dilakukan - menentukan apakah atau tidak satu blok kode> cocok untuk digunakan - tetapi saya tidak pernah benar-benar harus menulis unit test sebelumnya. (juga tidak pernah saya merasa perlu untuk ..)

Tes unit menulis memaksa kode Anda untuk menyesuaikan diri dengan struktur mental tertentu yang dapat diuji, didokumentasikan dengan baik, dan dapat diandalkan. Ini lebih dari apa yang Anda klaim.

-Saya Sudah membaca bahwa pengujian unit sering terjadi melalui penulisan "ejekan". Sementara saya memahami konsep ini, saya tidak bisa mencari tahu bagaimana saya seharusnya menulis ejekan untuk situs web yang sepenuhnya dinamis, dan di mana hampir semuanya tergantung pada data yang berasal dari database.

mengejek akses basis data dengan kelas tiruan yang mengembalikan kelas model yang diisi dengan data hardcoded yang terdefinisi dengan baik. atau , isi database uji dengan data fixture dan bekerja dari sana.

-Apakah kalian menyarankan saya untuk mulai menulis tes unit?

Yeah. Baca "Test Driven Development" Beck terlebih dahulu.

Saya pikir itu mungkin membantu saya dalam implementasi yang sebenarnya, tetapi sekali lagi saya merasa seperti itu mungkin memperlambat saya.

Ini memperlambat Anda sekarang. Tetapi ketika Anda harus men-debug berjam-jam bukannya berhari-hari, Anda akan berubah pikiran.

saran apa pun akan dihargai :)

Uji. Percayalah kepadaku. Sayangnya itu juga harus menjadi kebijakan manajemen, tetapi itu adalah sesuatu yang menghemat waktu. Tes tetap, mereka ada di sana, sekarang dan di masa depan. Ketika Anda mengubah platform, dan menjalankan tes, dan itu masih berfungsi, Anda tahu bahwa barang-barang Anda berfungsi seperti yang diharapkan.

Stefano Borini
sumber
8

Sunting: Saya tentu saja bergabung dengan dogpile pro / con TDD dan melewatkan pertanyaan # 1:

1 - Menerapkan tes unit dalam formulir web ASP.net:

Pertama-tama, jika Anda pikir Anda bisa membuat mereka menggunakan MVC, bertarunglah seperti layaknya ular rabbit. Sebagai front end / UI dev, .net MVC adalah apa yang membantu saya berhenti membenci .net sehingga saya bisa berkonsentrasi lebih baik pada membenci setiap solusi web Java yang pernah saya temui. Tes unit bermasalah karena formulir web benar-benar mengaburkan garis antara server dan sisi klien. Dalam setiap upaya untuk melakukan pengujian unit saya akan fokus pada manipulasi data dan (semoga) menganggap bentuk web menangani normalisasi input pengguna untuk Anda di bawah tenda.

2 - Tentang apakah tes unit bermanfaat pada awalnya:

Baiklah, pengungkapan penuh:

  • Saya kebanyakan belajar sendiri. Pelatihan formal saya bermula menjadi seperti JavaScript, PHP, dan kelas C # serta pembelajaran pribadi saya tentang prinsip-prinsip OOP dan membaca dari hal-hal seperti Pola Desain.

Namun,

  • Saya kebanyakan menulis untuk web sisi klien dan bagian pemrograman aktual yang ada di salah satu bahasa yang paling cepat dan longgar di luar sana dalam hal pengetikan dinamis, fungsi kelas satu, dan mutabilitas objek.

Itu artinya, saya tidak menulis untuk kompiler atau mesin virtual yang sama. Saya menulis sekitar 4-20 interpretasi yang berbeda-beda dari tiga bahasa (ya, dua di antaranya hanya bersifat deklaratif tetapi juga menentukan ruang fisik dasar dari UI yang kadang-kadang saya kerjakan dengan cara yang berbeda) dan telah melakukannya karena interpretasinya adalah jauh lebih bervariasi daripada sekarang. Dan tidak, saya bukan hanya anak-anak yang memasang barang-barang JQuery untuk aplikasi sekali pakai. Saya membantu membangun dan memelihara hal-hal yang cukup canggih dengan banyak kompleksitas elemen UI.

Jadi ya, ada banyak peluang untuk beberapa penyesuaian di sana-sini untuk menciptakan jajaran kegagalan besar-besaran jika keterampilan desain Anda benar-benar omong kosong atau Anda melempar dev biasa-biasa saja dalam jumlah besar pada 1-2 masalah kualitas dev.

Pemahaman saya tentang apa yang seharusnya dilakukan oleh TDD untuk Anda adalah bahwa tes tersebut benar-benar lebih tentang memaksa Anda untuk mempertimbangkan desain lebih hati-hati dan membuat Anda fokus pada persyaratan. Cukup adil, tetapi masalahnya di sini adalah merongrong apa yang harus Anda lakukan, yang merancang untuk antarmuka, untuk sesuatu yang secara halus tapi berbeda secara mendasar, yang merancang untuk pengujian antarmuka. Perbedaannya bagi saya adalah antara menggambar gambar yang jelas bahwa ibu tidak perlu menebak arti dan mengisi seluruh halaman dengan warna hijau dengan sangat cepat sehingga Anda bisa menjadi anak pertama yang menampar krayonnya di atas meja dan berteriak "selesai! " Dengan menggeser prioritas ke hasil daripada proses dan desain, Anda pada dasarnya mendorong penerapan kode sampah yang berkelanjutan, yang biasanya merupakan akar masalah Anda sejak awal.

Dan tentu saja ada manfaat samping "tidak-nyata-nyata" namun sering dipuji dari unit test itu sendiri yang membantu Anda mendeteksi kesalahan regresi. Pendukung TDD cenderung sedikit plin-plan pada apakah ini sebenarnya tujuan atau hanya efek samping yang bagus, IMO, karena mereka tahu betul atau curiga setidaknya ini tidak cukup untuk memastikan tidak adanya bug di komputer Anda. kode, terutama dalam bahasa yang lebih dinamis seperti JavaScript di mana Anda bahkan dapat memprediksi setiap skenario yang mungkin dalam rantai panjang dependensi adalah hal yang bodoh.

Ada tempat untuk pengujian otomatis di JS, tetapi penggunaan waktu Anda jauh lebih baik daripada melampirkan uji unit ke setiap 'unit' kode Anda yang bersentuhan dengan yang lain memastikan Anda tidak memiliki banyak objek sampah yang menduplikasi pekerjaan atau yang dimaksudkan penggunaannya secara semu ambigu di sana. Anda mengikuti prinsip KERING. Anda abstrak hal-hal untuk digunakan kembali / portabilitas ketika nilai melakukannya menjadi jelas (dan tidak semenit sebelumnya). Anda menetapkan proses dan cara yang konsisten untuk melakukan hal-hal yang mengikuti lebih banyak wortel daripada prinsip tetap (yaitu terlalu mudah menggunakan barang-barang Anda dengan cara yang benar untuk repot-repot ingin melakukannya dengan cara yang salah). Dan untuk cinta semua hal foo dan bar, Anda tidak pernah menikmati skema pewarisan cascading anti-pola sebagai sarana penggunaan kembali kode.

Semua hal di atas telah membantu saya mengurangi bug yang sulit didiagnosis dalam kode saya secara serius dan Anda dapat memercayai bahwa itu adalah prioritas besar bagi seseorang yang muncul sebagai pengembang dengan peramban yang tidak memiliki hal lain yang lebih baik untuk Anda ketahui daripada " eh ada masalah dengan objek bertipe 'Objek' di nomor baris imajiner ini dalam file yang tidak ditentukan. " (Wah, terima kasih IE6) TDD, di pekerjaan saya, tidak akan mendorong hal-hal ini. Ini akan mengalihkan fokus ke hasil 100% dari proses di mana apa antara titik A dan B tidak terlalu penting asalkan berfungsi. Ini adalah buang-buang waktu yang akan lebih baik diterapkan untuk memastikan barang-barang Anda dapat dibaca, portabel, dan mudah dimodifikasi tanpa banyak kerusakan yang membingungkan.

Atau mungkin saya hanya terlalu curam tentang paradigma yang saya gunakan, tetapi menurut saya, melakukannya dengan benar pada awalnya adalah penggunaan waktu yang jauh lebih efektif daripada menutupi pantat Anda ketika Anda atau orang lain menggunakan Tim melakukan kesalahan. Dan tidak ada yang harus memaksa Anda untuk mempertimbangkan desain alih-alih menyelesaikannya. Desain harus menjadi altar aneh setiap programmer. Dan segala sesuatu yang "memaksa Anda" untuk melakukan hal yang benar atau melindungi Anda dari diri Anda sendiri harus dilihat dengan kecurigaan yang sama dicadangkan untuk botol minyak ular, IMO. Minyak ular dalam TI modern dan pengembangan umum, jika Anda belum sadar, dijual oleh ton cair.

Erik Reppen
sumber
1
Saya menulis banyak tes unit. Saya tidak akan menulis kode tanpa mereka. Tapi saya setuju dengan sentimen Anda. Tes harus memandu , bukan mendorong pengembangan. Anda tidak dapat secara otomatis memikirkan masalah dengan cermat.
FizzyTea
Saya tidak punya masalah dengan pengujian otomatis. Tetapi adopsi grosir itu di setiap titik tampaknya lebih seperti panik daripada proses bagi saya. Menghemat waktu itu untuk merancang dan mengotomatiskan pengujian dan validasi pada titik-titik di mana Anda cenderung berinteraksi dengan berbagai hal yang tidak Anda kendalikan adalah cara saya lebih suka.
Erik Reppen
5

Dalam pengalaman saya, tes unit memang sangat berguna, ketika Anda mulai dengan mereka dan tetap dengan mereka yaitu Pengembangan Test-Driven. Inilah alasannya:

  • Tes unit memaksa Anda untuk berpikir tentang apa yang Anda inginkan, dan bagaimana memverifikasi bahwa Anda mendapatkannya, sebelum Anda menulis kode yang melakukannya . Dalam skenario TDD, Anda menulis tes terlebih dahulu. Karena itu Anda harus tahu kode apa yang hendak Anda tulis perlu dilakukan, dan bagaimana Anda dapat memverifikasi bahwa kode itu berhasil melakukannya, untuk menulis tes "merah" yang kemudian Anda buat "hijau" dengan menulis kode ke lulus saja. Dalam banyak kasus ini memaksa Anda untuk berpikir sedikit lebih banyak tentang algoritma yang akan Anda tulis untuk lulus tes ini, yang selalu merupakan hal yang baik karena mengurangi kesalahan logika dan "kasus sudut". Saat Anda menulis tes, Anda berpikir "bagaimana ini bisa gagal" dan "apa yang tidak saya uji di sini", yang mengarah ke algoritma yang lebih kuat.

  • Tes unit memaksa Anda untuk berpikir tentang bagaimana kode yang akan Anda tulis akan dikonsumsi . Sebelum saya belajar TDD, ada banyak waktu di mana saya menulis kode mengharapkan ketergantungan untuk bekerja satu arah, dan kemudian diberi ketergantungan yang ditulis oleh seorang rekan kerja yang bekerja dengan cara yang sama sekali berbeda. Meskipun hal ini masih dimungkinkan dengan TDD, unit test yang Anda tulis memaksa Anda untuk berpikir tentang bagaimana Anda ingin menggunakan objek yang Anda tulis, karena ini adalah contoh penggunaan objek tersebut. Anda kemudian diharapkan akan menulis objek sedemikian rupa sehingga mudah dikonsumsi, dan dengan demikian untuk beradaptasi jika perlu (meskipun pemrograman ke antarmuka yang telah ditentukan adalah solusi keseluruhan yang lebih baik untuk masalah ini yang tidak memerlukan TDD).

  • Tes unit memungkinkan Anda untuk "kode dengan pengujian" . Alat refactoring seperti ReSharper bisa menjadi teman terbaik Anda jika Anda membiarkannya. Anda dapat menggunakannya untuk menentukan kerangka fungsionalitas baru saat Anda mendefinisikan penggunaan dalam suatu pengujian.

    Misalnya, Anda perlu membuat objek MyClass baru. Anda mulai dengan membuat instance dari MyClass. "Tapi MyClass tidak ada!", ReSharper mengeluh. "Kalau begitu buat", katamu, dengan menekan Alt + Enter. Dan presto Anda memiliki definisi kelas Anda. Pada baris kode uji berikutnya Anda memanggil metode MyMethod. "Tapi itu tidak ada!", Kata ReSharper. "Kalau begitu buat", ulangi, dengan Alt + Enter lainnya. Anda telah, dengan beberapa penekanan tombol, menetapkan "kerangka" kode baru Anda. Ketika Anda terus menyempurnakan penggunaannya, IDE akan memberi tahu Anda ketika ada sesuatu yang tidak cocok, dan biasanya solusinya cukup sederhana sehingga IDE atau alat yang terhubung dengannya tahu cara memperbaikinya.

    Contoh yang lebih ekstrem sesuai dengan model "Triple-A"; "Atur, Kerjakan, Tegas". Atur semuanya, lakukan logika aktual yang Anda uji, kemudian tegaskan bahwa logika itu benar. Pengodean dengan cara ini, sangat alami untuk mengkodekan solusi ke dalam pengujian; kemudian, dengan beberapa penekanan tombol, Anda dapat mengekstrak logika itu dan meletakkannya di suatu tempat di mana ia dapat digunakan dalam kode produksi, kemudian membuat perubahan kecil pada tes yang mengarahkannya ke lokasi baru dari logika. Melakukannya dengan cara ini memaksa Anda untuk merancang kode dengan cara modular, mudah digunakan kembali karena unit yang Anda uji masih harus dapat diakses.

  • Tes unit menjalankan banyak urutan lebih cepat daripada tes manual yang dapat Anda pikirkan. Ada satu titik, sangat cepat dipenuhi dalam kasus proyek yang lebih besar, di mana waktu overhead pengujian unit mulai membayar sendiri dengan mengurangi waktu yang dihabiskan untuk pengujian secara manual. Anda harus SELALU menjalankan kode yang baru saja Anda tulis. Secara tradisional, Anda melakukannya secara manual, dengan memulai program besar, menavigasi melalui UI untuk mengatur situasi Anda telah mengubah perilaku, dan kemudian memverifikasi hasilnya lagi melalui UI, atau dalam bentuk data yang dihasilkan. Jika kode itu TDDed, Anda hanya menjalankan tes unit. Saya jamin jika Anda menulis unit test yang baik, opsi yang terakhir akan jauh lebih cepat daripada yang sebelumnya.

  • Tes unit menangkap regresi . Sekali lagi, ada beberapa kali sebelum saya mempelajari TDD di mana saya masuk, membuat apa yang saya pikir adalah perubahan bedah menjadi sepotong kode, memverifikasi bahwa perubahan itu memperbaiki perilaku yang salah (atau menghasilkan perilaku yang diinginkan baru) dalam situasi yang dilaporkan. , dan memeriksanya untuk rilis, hanya untuk menemukan bahwa perubahan memecahkan beberapa kasus sudut lain dalam modul yang sama sekali berbeda yang kebetulan menggunakan kembali blok kode yang sama. Dalam proyek TDDed, saya dapat menulis tes memverifikasi perubahan yang akan saya buat, membuat perubahan, kemudian menjalankan paket lengkap, dan jika semua penggunaan kode lainnya TDDed dan perubahan saya memecahkan sesuatu, tes untuk mereka hal-hal lain akan gagal, dan saya bisa menyelidikinya.

    Jika pengembang harus secara manual menemukan dan menguji semua baris kode yang dapat dipengaruhi oleh perubahan potensial, tidak ada yang bisa dilakukan karena biaya menentukan dampak perubahan akan membuat membuat perubahan tidak layak. Paling tidak, tidak ada yang SOLID dan dengan demikian mudah dipelihara, karena Anda tidak akan pernah berani menyentuh sesuatu yang dapat digunakan di banyak tempat; Anda sebaliknya akan menggulung solusi Anda sendiri yang sangat mirip tetapi memasukkan perubahan minor Anda untuk kasus ini, melanggar SRP dan mungkin OCP, dan perlahan-lahan mengubah basis kode Anda menjadi selimut tambal sulam.

  • Tes unit membentuk arsitektur dengan cara yang biasanya menguntungkan . Tes unit adalah tes yang dilakukan secara terpisah dari logika lain. Agar unit dapat menguji kode Anda, maka, Anda harus menulis kode sedemikian rupa sehingga Anda bisamengisolasinya. Keputusan desain yang baik seperti kopling longgar dan injeksi ketergantungan dengan demikian secara alami menyingkirkan proses TDD; dependensi harus disuntikkan sehingga dalam tes Anda dapat menyuntikkan "tiruan" atau "rintisan" yang menghasilkan input atau menangani output untuk situasi yang sedang diuji tanpa membuat "efek samping". Mentalitas "penggunaan pertama" TDD umumnya mengarah ke "pengkodean ke antarmuka", esensi dari kopling longgar. Prinsip-prinsip desain yang baik ini kemudian memungkinkan Anda untuk membuat perubahan dalam produksi seperti mengganti seluruh kelas, tanpa memerlukan banyak basis kode untuk diubah untuk beradaptasi.

  • Tes unit menunjukkan bahwa kode berfungsi, alih-alih membuktikan bahwa kode berfungsi . Pada pandangan pertama Anda mungkin berpikir itu suatu kerugian; tentu buktinya lebih baik dari pada demonstrasi? Teori hebat; teori komputasi dan algoritmik adalah dasar dari pekerjaan kami. Tapi, bukti matematis kebenaran dari suatu algoritma adalah tidak bukti kebenaran pelaksanaan . Bukti matematis hanya menunjukkan bahwa kode yang mengikuti algoritma harus benar. Sebuah tes unit menunjukkan bahwa kode benar-benar ditulis melakukan apa yang Anda pikir itu akan dilakukan, dan dengan demikian bukti itu adalah benar. Ini umumnya jauh lebih bernilai daripada bukti teoretis.

Sekarang, semua yang dikatakan, ada kerugian untuk pengujian unit:

  • Anda tidak dapat menguji semuanya. Anda dapat merancang sistem Anda untuk meminimalkan jumlah LOC yang tidak tercakup oleh tes unit, tetapi ada beberapa area sistem yang tidak dapat diuji unit. Lapisan akses data Anda dapat diejek ketika digunakan oleh kode lain, tetapi lapisan akses data itu sendiri mengandung banyak efek samping dan biasanya tidak layak untuk menguji banyak unit (sebagian besar?) Dari Repositori atau DAO. Demikian pula, kode yang menggunakan file, mengatur koneksi jaringan, dll. Memiliki efek samping bawaan dan Anda tidak dapat menguji unit dari baris kode yang melakukan itu. Elemen UI sering tidak dapat diuji unit; Anda dapat menguji metode kode belakang seperti penangan peristiwa, Anda dapat unit konstruktor uji dan memverifikasi bahwa penangan dicolokkan, tetapi tidak ada pengganti dalam kode untuk pengguna mengklik mouse pada elemen grafis tertentu dan menonton pawang dipanggil. Mencapai batas-batas ini antara apa yang bisa dan tidak bisa diuji unit secara memadai disebut "mengikis tepi kotak pasir"; Selain itu Anda dibatasi untuk menggunakan tes integrasi, tes penerimaan otomatis, dan pengujian manual untuk memverifikasi perilaku.

  • Banyak keuntungan dari pengujian unit tidak berlaku tanpa TDD. Sangat mungkin untuk menulis kode, kemudian menulis tes yang melatih kode. Mereka masih "unit test", namun dengan menulis kode terlebih dahulu, Anda kehilangan banyak keuntungan yang melekat dalam pengembangan "test-first": kode tidak harus dirancang dengan cara yang dapat dengan mudah diuji, atau bahkan digunakan dalam produksi ; Anda tidak mendapatkan proses berpikir "periksa ulang" yang melekat dalam penulisan tes dan pikirkan apa yang tidak Anda pikirkan; Anda tidak membuat kode dengan pengujian; dan jika Anda menulis kode, mengujinya secara manual dan melihatnya berfungsi, lalu mengode uji unit yang gagal, yang salah, kode atau tes? Keuntungan utama Anda adalah pencegahan regresi (Anda akan diberitahu ketika kode yang sebelumnya lulus pengujiannya sekarang gagal) dan verifikasi berkecepatan tinggi versus pengujian manual. Hilangnya TDD '

  • Pengujian unit memperkenalkan overhead . Sederhananya, Anda sedang menulis kode untuk menguji kode yang Anda tulis. Ini tentu akan meningkatkan total LOC dari proyek pengembangan, dan ya, LOC untuk tes dapat melebihi LOC untuk proyek yang sebenarnya. Pengembang naif dan non-pengembang akan melihat keadaan ini dan mengatakan tes itu buang-buang waktu.

  • Pengujian unit membutuhkan disiplin. Anda harus menulis tes yang akan menjalankan basis kode (cakupan kode yang baik) secara memadai, Anda harus menjalankannya secara teratur (seperti setiap kali Anda melakukan perubahan, paket lengkap harus dijalankan), dan Anda harus menjaga semuanya "hijau" ( semua tes lulus). Ketika ada masalah, Anda harus memperbaikinya dengan memperbaiki kode yang tidak memenuhi harapan, atau dengan memperbarui harapan tes. Jika Anda mengubah tes, Anda harus bertanya "mengapa", dan mengawasi diri Anda sendiri; itu sangat menggoda untuk hanya mengubah pernyataan gagal untuk mencocokkan perilaku saat ini, atau hanya menghapus tes gagal; tetapi, tes tersebut harus berdasarkan pada persyaratan, dan ketika keduanya tidak cocok Anda memiliki masalah. Jika hal-hal ini tidak dilakukan,

  • Pengujian unit membutuhkan lebih banyak peralatan. Solusi biasa untuk kebutuhan di atas untuk disiplin, dan kecenderungan alami manusia untuk menjadi malas dan puas, adalah "build-bot" menjalankan paket perangkat lunak "Integrasi Berkelanjutan" seperti TeamCity, CruiseControl, dll, yang melakukan pengujian unit, menghitung metrik cakupan kode, dan memiliki kontrol lain seperti "triple-C" (kepatuhan konvensi pengkodean, ala FxCop). Perangkat keras untuk build-bot harus berkinerja wajar (jika tidak, ia tidak akan mengikuti laju check-in kode yang akan dibuat oleh tim rata-rata), dan prosedur check-in pada bot harus selalu diperbarui (jika perpustakaan baru tes unit dibuat, buat skrip yang menjalankan tes unit harus diubah untuk melihat di perpustakaan itu). Ini kurang bekerja daripada kedengarannya, tetapi biasanya memerlukan beberapa keahlian teknis pada bagian dari setidaknya beberapa orang di tim yang tahu bagaimana seluk-beluk berbagai proses membangun bekerja (dan dengan demikian dapat mengotomatisasi mereka dalam skrip dan memelihara skrip tersebut). Itu juga masih membutuhkan disiplin dalam bentuk memperhatikan ketika membangun "istirahat", dan memperbaiki apa pun yang menyebabkan rusak (benar) sebelum memeriksa sesuatu yang baru.

  • Pengujian unit dapat memaksa kode untuk dirancang secara tidak ideal . Walaupun TDD biasanya baik untuk modularitas dan penggunaan kembali kode, ini dapat merusak aksesibilitas kode yang tepat. Objek dan anggota, ditempatkan di perpustakaan produksi, tidak bisa bersifat pribadi atau internal jika mereka langsung digunakan oleh unit test. Ini dapat menyebabkan masalah ketika coders lain, sekarang melihat objek, mencoba menggunakannya ketika mereka seharusnya menggunakan sesuatu yang ada di perpustakaan. Ulasan kode dapat membantu dengan ini, tetapi bisa menjadi perhatian.

  • Pengujian unit umumnya melarang gaya pengkodean "pengembangan aplikasi cepat". Jika Anda menulis unit test, Anda tidak mengkodekan "cepat-dan-longgar". Itu biasanya hal yang baik, tetapi ketika Anda berada di bawah tenggat waktu yang dipaksakan dari luar kendali Anda, atau Anda menerapkan perubahan dengan cakupan yang sangat kecil dan pemangku kepentingan (atau bos Anda) bertanya-tanya mengapa semua kesalahan ini harus terjadi hanya untuk mengubah satu baris kode, itu hanya tidak layak untuk menulis dan memelihara unit test suite yang tepat. Proses lincah biasanya membantu dengan ini dengan memungkinkan pengembang mengatakan dalam persyaratan waktu; ingat, yang harus dilakukan oleh penjual adalah mengatakan "ya kita bisa" dan mereka mendapatkan cek komisi, kecuali prosesnya melibatkan orang-orang yang benar-benar harus melakukan pekerjaan dengan mengatakan "tidak kita tidak bisa" dan diperhatikan. Tapi, tidak semua orang tangkas, dan tangkas memiliki keterbatasannya sendiri.

KeithS
sumber
4

Tes unit berguna bila digunakan dengan benar; ada berbagai masalah dengan logika Anda.

"Ketika saya berkembang, saya mengalami banyak trial-and-error," kata Kevin.

Lihatlah pemrograman secara kebetulan. Lebih baik untuk memahami apa yang harus dilakukan kode dan kemudian membuktikannya melalui uji unit. Jangan menganggap kode berfungsi hanya karena UI tidak rusak ketika Anda menjalankan program!

s writing unit tests for ASP.NET web forms something that is done often

Saya tidak memiliki pengetahuan tentang data statistik untuk mengatakan seberapa sering orang menguji formulir web. Tidak masalah. UI sulit untuk diuji dan Tes Unit juga tidak boleh digabungkan ke UI. Pisahkan logika Anda ke dalam layer, pustaka kelas yang dapat diuji. Tes UI secara terpisah dari logika back-end.

So, question number 2: Would you guys advise me to start writing unit tests?

Iya. Setelah Anda terbiasa dengan mereka, mereka mempercepat Anda. Pemeliharaan jauh lebih memakan waktu dan mahal daripada fase pengembangan awal. Perawatan sangat terbantu dengan pengujian unit, bahkan dengan pengujian awal dan perbaikan bug.

P.Brian.Mackey
sumber
Ada kerangka kerja pengujian di luar sana yang dapat melakukan pengujian pada halaman aspx untuk hanya menguji apakah halaman berhasil dimuat atau tidak dalam skenario yang berbeda. Ini mungkin tidak cukup baik, tetapi lebih baik daripada tidak sama sekali.
awe
4

Pada level praktis Tes unit bisa sangat berguna untuk satu alasan yang sangat penting: Anda dapat menguji satu bit kode pada satu waktu.

Ketika Anda menulis seluruh urutan langkah-langkah kompleks dan men-debugnya di akhir, Anda cenderung menemukan banyak bug, dan prosesnya biasanya lebih sulit karena Anda lebih jauh dalam prosesnya. Di Visual Studio Anda dapat membuat tes cepat, ubah sedikit dan jalankan HANYA tes itu .. Anda kemudian tahu bahwa misalnya metode memanggil metode yang dapat diandalkan. Jadi itu meningkatkan kepercayaan diri.

Tes unit tidak membuktikan bahwa program Anda benar! : Tes unit memeriksa regresi dalam kode sensitif dan memungkinkan Anda menguji metode baru yang Anda tulis.

Tes unit tidak dimaksudkan untuk menguji ujung-depan : Pikirkan tes unit sebagai proyek kecil yang Anda buat untuk menguji metode baru yang Anda tulis atau apalah, bukan semacam kondisi yang harus dipenuhi oleh kode Anda.

Pengujian unit berfungsi baik untuk lingkungan kolaboratif : Jika saya harus menyediakan metode kepada kolega yang menggunakan teknologi yang sama sekali berbeda untuk menambang, seperti misalnya ia memanggilnya dari iOS, maka saya dapat dengan cepat menulis unit test untuk melihat apakah metode yang dia inginkan a) Mengembalikan data yang benar b) Melakukan sesuai spesifikasinya c) Tidak memiliki hambatan yang buruk.

Tjaart
sumber
"Tes unit tidak dimaksudkan untuk menguji ujung depan" Siapa bilang itu? Saya tidak mempertanyakannya. Saya hanya ingin tahu karena banyak orang tampaknya memiliki ide yang salah dan saya ingin menghajar mereka dengan yang-tidak-apa-ini-sangat-berpengaruh-TDD-advokat-sumber-kata tongkat.
Erik Reppen
Beberapa orang, termasuk saya sendiri, memiliki kesalahpahaman itu ketika pertama kali menghadapi unit test, jadi saya baru saja menyelesaikannya. Saya tidak tahu mengapa Anda merasa seperti saya menantang Anda, bahkan saya sepenuhnya setuju dengan Anda.
Tjaart
4

Satu hal yang tampaknya tidak disentuh adalah kompleksitas pengujian berbagai jenis kode.

Ketika Anda berurusan dengan hal-hal dengan input dan output sederhana, umumnya mudah untuk menguji unit dan jika tes dipilih dengan pikiran ke tepi kasus kode yang diuji mereka akan memberi Anda banyak kepercayaan bahwa mereka benar. Tidak menulis tes untuk kode seperti itu akan gila. (Perhatikan bahwa sebagian besar kode yang masuk ke perpustakaan memenuhi kriteria ini.)

Namun, dalam kasus lain, Anda akhirnya harus membuat tiruan besar untuk diuji karena kode tersebut bermain dengan data dasar yang kompleks (biasanya database tetapi tidak harus) atau menghasilkan data output yang sangat kompleks (pikirkan rutin yang berubah nilai seed ke level game untuk contoh yang cukup ekstrim) dan pengujian unit hampir tidak berguna. Mencakup semua yang ada dalam kasing uji biasanya merupakan mimpi buruk dan ketika Anda menemukan bug, kasing itu hampir selalu merupakan kasing yang tidak pernah terpikirkan oleh Anda dan karenanya tidak bisa membuat tes.

Tidak ada peluru perak, apa pun yang digambarkan sebagai peluru perak tidak sebagus yang diklaim para pendukungnya, tetapi itu tidak berarti itu tidak berguna.

Loren Pechtel
sumber
4

Tes unit penulisan untuk formulir aplikasi ASP.NET Web TIDAK umum dan sangat sulit untuk dicapai. Namun, itu tidak berarti bahwa proyek tersebut harus melewati itu.

Tes unit adalah corner stonesaplikasi penting misi dan memberikan keandalan dan ketenangan pikiran yang menjalankan fungsi inti seperti yang diharapkan.

Sebenarnya Anda dapat memperkenalkan pengujian unit jauh lebih mudah dengan pola ASP.NET MVP yang dapat digunakan dalam pengembangan formulir web Anda. Ini akan memperkenalkan pemisahan masalah dan ability to write essential unit tests.

Beberapa referensi yang mungkin bermanfaat untuk dilihat adalah:

ElYusubov
sumber
2
+1 Tidak masalah jika Anda melakukan tes unit atau tidak, MVP adalah cara untuk bekerja ketika bekerja dengan Formulir Web (mungkin juga WinForms).
simoraman
3

Tujuan dari tes unit adalah untuk memungkinkan Anda mengubah kode Anda dengan aman (refactoring, meningkatkan dll) tanpa takut bahwa Anda dapat merusak sesuatu di dalam sistem. Ini terbukti sangat berguna untuk aplikasi besar, ketika Anda tidak benar-benar tahu semua efek dari perubahan kode Anda (meskipun kopling longgar).

m3th0dman
sumber
6
Tanpa rasa takut adalah rasa aman yang salah.
Coder
Mungkin "kurang takut" adalah ungkapan yang lebih baik, tetapi jawabannya sebagian besar masih benar.
Brendan Long
1
@Coder Jika tes Anda lulus setelah refactoring, maka Anda dapat yakin bahwa peningkatan kode tidak mengubah cara aplikasi berperilaku (secara kasar Anda tidak memperkenalkan bug baru, tetapi ini tidak selalu benar karena Anda tidak dapat mencapai Cakupan tes 100%).
m3th0dman
2

Ini pengalaman saya bahwa ya , tes unit bermanfaat.

Unit Testing adalah tentang memisahkan bagian-bagian dari kode yang Anda tulis dan memastikan bahwa mereka bekerja secara terpisah. Isolasi ini mungkin melibatkan pembuatan objek palsu atau tiruan untuk berbicara dengan objek yang Anda uji, atau mungkin juga tidak. Itu sangat tergantung pada arsitektur objek Anda.

Pengujian unit memberikan berbagai manfaat:

Terutama, ini memastikan bahwa unit yang Anda uji bekerja dengan cara Anda, pengembang, berpikir mereka harus bekerja. Meskipun ini kurang dari kedengarannya: itu tidak selalu mengatakan bahwa objek berfungsi dengan benar; hanya saja itu berfungsi seperti yang Anda pikirkan seharusnya, itu adalah pernyataan yang jauh lebih kuat daripada metode coba-coba yang diperlukan tanpa pengujian unit.

Selain itu, memastikan bahwa unit terus bekerja dengan cara Anda, pengembang, berpikir mereka harus bekerja. Perubahan perangkat lunak, dan ini dapat memengaruhi unit dengan cara yang tidak terduga.

Lain efek samping adalah bahwa hal itu berarti bahwa unit Anda menguji melakukan pekerjaan dalam isolasi. Ini umumnya berarti bahwa Anda mulai pemrograman ke antarmuka daripada kelas konkret, mengurangi sambungan dan meningkatkan kohesi: semua ciri umum desain yang baik. Ya: hanya mengaktifkan unit kode Anda untuk memiliki tes unit akan secara alami meningkatkan desain kode Anda.

Namun...

Unit Testing bukan akhir dari pengujian. Jenis pengujian lain masih diperlukan. Misalnya, bahkan ketika Anda telah menunjukkan bahwa unit bekerja dengan cara yang Anda harapkan, Anda masih perlu menunjukkan bahwa setiap unit bekerja seperti halnya unit yang berbicara dengannya mengharapkannya bekerja. Yaitu, apakah komponen Anda terintegrasi satu sama lain dengan benar?

Kaz Dragon
sumber
1

Untuk aplikasi sederhana dengan sejumlah kecil lapisan untuk diuji (Jendela utama -> sub menu), mungkin kompilasi untuk menjalankan untuk memeriksa perubahan tidak masalah.

Untuk aplikasi yang lebih besar di mana dibutuhkan navigasi 30an untuk mendapatkan halaman yang Anda uji, ini akhirnya menjadi sangat mahal ..

DefenestrationDay
sumber
1

Saya ingin menambahkan sisi baru (sebenarnya, yang agak lama) untuk ini: tes unit tidak berguna jika kode Anda dirancang dengan baik .

Saya tahu sebagian besar programmer tidak melakukan desain program lagi, saya masih melakukannya, dan saya menemukan tes unit menjadi kebutuhan yang agak memakan waktu untuk masuk ke dalam budaya TDD, tetapi sejauh ini, saya hanya bertemu 1-2 minor bug per ribuan baris tes kode saya - tidak hanya apa yang saya tulis, tetapi apa yang ditulis penguji resmi juga.

Saya kira Anda tidak akan lagi melakukan desain program - orang-orang saat ini akan menekan Anda agar tidak melakukannya - tetapi mungkin perlu diingat bahwa unit test adalah metode efisiensi yang sangat-sangat rendah dibandingkan dengan desain.

Ini adalah argumen yang dijsktraian: unit test hanya dapat dijalankan terhadap program yang cukup detail untuk dijalankan.

Jika Anda menggambar diagram alir / diagram keadaan / tindakan, diagram urutan, inventaris objek (dan AND terakhir, diagram kelas) untuk kode Anda sebelum benar-benar menulisnya, Anda akan dapat membunuh sebagian besar bug yang berpotensi mengancam hanya dengan menelusuri sekitar baris Anda dan memeriksa nama Anda.

Saat ini diagram kelas dihasilkan dari kode, yang berisi ratusan, kadang-kadang ribuan kelas dan benar-benar tidak dapat digunakan - apa pun yang mengandung lebih dari 15 elemen tidak dapat dikenali manusia.

Anda harus tahu apa 10 + -5 kelas penting atau apa yang Anda lakukan sekarang, dan dapat memeriksa kode Anda dari beberapa sudut pandang, setiap diagram mewakili PERSIS sudut pandang yang Anda lihat, dan Anda akan membunuh ribuan bug di kertas.

  • Memeriksa kode dinamis jika jenis terpenuhi (dengan hanya menunjukkan jenis input / output pada diagram alur dan menghubungkannya dengan pensil atau warna berbeda),
  • memeriksa apakah semua negara ditangani (dengan memeriksa kepenuhan kondisi Anda),
  • menelusuri garis-garis untuk memastikan semuanya berakhir (setiap diagram alur harus menjadi otomat keadaan terbatas deterministik yang terdefinisi sepenuhnya, untuk yang berpikir matematis
  • memastikan bahwa komponen-komponen tertentu tidak ada hubungannya satu sama lain (dengan mengekstraksi semua dependensinya) (baik untuk keamanan)
  • menyederhanakan kode dengan mengubah dependensi menjadi asosiasi (dependensi berasal dari kelas apa yang digunakan metode anggota)
  • memeriksa nama, mencari awalan umum, menghapus sinonim dll ...

ada jauh lebih mudah ...

Juga, saya menemukan bahwa aplikasi saya lebih bisa digunakan, jika mereka datang langsung dari kasus penggunaan ... jika kasus penggunaan ditulis dengan baik (subjek kata kerja ACTOR, permintaan Maintainer untuk membuka mesin ATM) ... Itu

Saya sudah melakukan kode dengan 95% cakupan kode. Tentu saja, saya kadang-kadang melakukan tes unit, khususnya. untuk pemeriksaan batas dalam perhitungan, tapi saya belum memenuhi regresi serius (serius: tidak hilang dalam 24 jam) karena tidak menggunakan tes unit bahkan untuk refactor.

Terkadang saya tidak melakukan satu baris kode selama 3-4 hari berturut-turut, hanya menggambar. Kemudian, dalam satu hari, saya mengetikkan 1500-2000 baris. Pada hari berikutnya, kebanyakan sudah siap berproduksi. Kadang-kadang tes unit ditulis (dengan cakupan 80%), kadang-kadang (sebagai tambahan) penguji diminta untuk mencoba memecahkannya, setiap kali, beberapa orang diminta untuk memeriksanya dengan melihatnya.

Saya belum melihat unit test menemukan apa pun.

Saya berharap pemikiran desain akan menggantikan TDD ... tapi TDD jauh lebih mudah, itu seperti pergi dengan palu godam ... mendesain pemikiran kebutuhan, dan Anda sering berada di papan tombol untuk sebagian besar waktu.

Aadaam
sumber
Saya pikir Anda dapat mendesain di keyboard. Tetapi perencanaan dan pengorganisasian kode memang membutuhkan banyak pemikiran lebih dari sekadar tersandung melalui input ke output di kelas yang mungkin juga fungsi monolitik.
Erik Reppen
Percayalah, fungsi monolitik tidak sesuai dengan kertas A4 (atau US Letter). Kadang-kadang ketika saya malas saya melakukan "desain" di keyboard, tapi kualitasnya tidak sama. Setiap kali saya melakukan pengembangan serius, saya melakukan desain dengan UML. Ketika Anda menggambar ini, Anda mencoba menjelaskan kepada diri sendiri dan orang lain dengan cara yang sangat terbatas tetapi masih terstruktur apa yang terjadi, dan ketika Anda dapat menjelaskan kode dari setiap perspektif tunggal, maka, hanya saat Anda mengetik masuk, dan tiba-tiba semua bug Anda paling banyak kesalahan pengetikan ...
Aadaam