Saya mengajukan pertanyaan ini mengenai masalah yang saya alami selama proyek TDD. Saya perhatikan tantangan berikut saat membuat unit test.
- Menghasilkan dan memelihara data tiruan
Sulit dan tidak realistis untuk mempertahankan data tiruan besar. Ini bahkan lebih sulit ketika struktur basis data mengalami perubahan.
- Menguji GUI
Bahkan dengan MVVM dan kemampuan untuk menguji GUI, dibutuhkan banyak kode untuk mereproduksi skenario GUI.
- Menguji bisnis
Saya memiliki pengalaman bahwa TDD berfungsi dengan baik jika Anda membatasinya pada logika bisnis sederhana. Namun logika bisnis yang kompleks sulit untuk diuji karena jumlah kombinasi tes (ruang uji) sangat besar.
- Kontradiksi dalam persyaratan
Pada kenyataannya sulit untuk menangkap semua persyaratan dalam analisis dan desain. Berkali-kali satu persyaratan catatan menimbulkan kontradiksi karena proyek ini kompleks. Kontradiksi ditemukan terlambat di bawah tahap implementasi. TDD mensyaratkan bahwa persyaratannya 100% benar. Dalam kasus seperti itu, orang dapat berharap bahwa persyaratan yang bertentangan akan ditangkap selama pembuatan tes. Tetapi masalahnya adalah bahwa ini tidak terjadi dalam skenario yang kompleks.
Saya telah membaca pertanyaan ini: Mengapa TDD berfungsi?
Apakah TDD benar-benar berfungsi untuk proyek-proyek perusahaan yang kompleks, atau apakah itu praktis terbatas pada jenis proyek?
Jawaban:
Salah.
Pengujian unit tidak memerlukan data tiruan "besar". Ini membutuhkan data tiruan yang cukup untuk menguji skenario dan tidak lebih.
Juga, programmer yang benar-benar malas meminta ahli materi pelajaran untuk membuat lembar kerja sederhana dari berbagai kasus uji. Hanya spreadsheet sederhana.
Kemudian programmer malas menulis skrip sederhana untuk mengubah baris spreadsheet menjadi unit uji kasus. Ini sangat sederhana, sungguh.
Ketika produk berevolusi, spreadsheet dari kasus uji diperbarui dan tes unit baru dihasilkan. Lakukan sepanjang waktu. Ini benar-benar berfungsi.
Apa? "Reproduksi"?
Maksud dari TDD adalah untuk Merancang hal-hal untuk Testability (Pengembangan Drive Test). Jika GUI sangat kompleks, maka harus didesain ulang agar lebih sederhana dan lebih dapat diuji. Simpler juga berarti lebih cepat, lebih mudah dirawat dan lebih fleksibel. Tetapi sebagian besar lebih sederhana akan berarti lebih dapat diuji.
Itu bisa benar.
Namun, meminta ahli materi pelajaran untuk memberikan kasus uji inti dalam bentuk sederhana (seperti spreadsheet) sangat membantu.
Spreadsheet bisa menjadi agak besar. Tapi tidak apa-apa, karena saya menggunakan skrip Python sederhana untuk mengubah spreadsheet menjadi kasus uji.
Dan. Saya memang harus menulis beberapa test case secara manual karena spreadsheet tidak lengkap.
Namun. Ketika pengguna melaporkan "bug", saya hanya bertanya kasus uji mana dalam spreadsheet yang salah.
Pada saat itu, para ahli materi akan mengoreksi spreadsheet atau mereka akan menambahkan contoh untuk menjelaskan apa yang seharusnya terjadi. Laporan bug dapat - dalam banyak kasus - secara jelas didefinisikan sebagai masalah kasus uji. Memang, dari pengalaman saya, mendefinisikan bug sebagai test case yang rusak membuat diskusi jauh lebih mudah.
Daripada mendengarkan para ahli mencoba menjelaskan proses bisnis yang sangat kompleks, para ahli harus menghasilkan contoh nyata dari proses tersebut.
Tidak menggunakan TDD benar-benar mengamanatkan bahwa persyaratannya 100% benar. Beberapa mengklaim bahwa TDD dapat mentolerir persyaratan yang tidak lengkap dan berubah, di mana pendekatan non-TDD tidak dapat bekerja dengan persyaratan yang tidak lengkap.
Jika Anda tidak menggunakan TDD, kontradiksi ditemukan terlambat dalam tahap implementasi.
Jika Anda menggunakan TDD kontradiksi ditemukan sebelumnya ketika kode melewati beberapa tes dan gagal tes lainnya. Memang, TDD memberi Anda bukti kontradiksi sebelumnya dalam proses, jauh sebelum implementasi (dan argumen selama pengujian penerimaan pengguna).
Anda memiliki kode yang lulus beberapa tes dan gagal lainnya. Anda hanya melihat tes-tes itu dan Anda menemukan kontradiksinya. Ini bekerja sangat, sangat baik dalam praktiknya karena sekarang pengguna harus berdebat tentang kontradiksi dan menghasilkan contoh-contoh konkret dari perilaku yang diinginkan.
sumber
Iya
Paparan pertama saya ke TDD sedang mengerjakan komponen middleware untuk ponsel berbasis Linux. Yang akhirnya menjadi jutaan baris kode sumber, yang pada gilirannya disebut menjadi sekitar 9 gigabyte kode sumber untuk berbagai komponen sumber terbuka.
Semua penulis komponen diharapkan untuk mengusulkan API dan satu set unit test, dan meminta mereka ditinjau oleh panitia. Tidak ada yang mengharapkan kesempurnaan dalam pengujian, tetapi semua fungsi yang terpapar secara publik harus memiliki setidaknya satu tes, dan sekali komponen diserahkan kepada kontrol sumber, semua tes unit harus selalu lulus (bahkan jika mereka melakukannya karena komponen tersebut secara salah melaporkan itu bekerja dengan baik).
Tidak diragukan lagi karena setidaknya sebagian untuk TDD dan desakan bahwa semua tes unit selalu berlalu, rilis 1.0 datang lebih awal, di bawah anggaran, dan dengan stabilitas yang mencengangkan.
Setelah rilis 1.0, karena perusahaan ingin dapat dengan cepat mengubah ruang lingkup karena permintaan pelanggan, mereka mengatakan kepada kami untuk berhenti melakukan TDD, dan menghapus persyaratan yang harus dilewati unit test. Sungguh mengherankan betapa cepatnya kualitas turun ke toilet, dan kemudian jadwal mengikutinya.
sumber
removed the requirement that unit tests pass. It was astonishing how quickly quality went down the toilet, and then the schedule followed it.
- Ini seperti memberi tahu pembalap F1 Anda bahwa ia tidak diizinkan Berhenti Pit karena butuh terlalu banyak waktu ... Idiotik.Saya berpendapat bahwa semakin kompleks proyek, semakin banyak manfaat yang Anda dapatkan dari TDD. Manfaat utama adalah efek samping dari bagaimana TDD akan memaksa Anda untuk menulis kode dalam potongan yang jauh lebih kecil, jauh lebih mandiri. Manfaat utama adalah:
a) Anda mendapatkan validasi desain jauh lebih awal karena loop umpan balik Anda jauh lebih ketat karena tes dari awal.
b) Anda dapat mengubah sedikit demi sedikit dan melihat bagaimana sistem bereaksi karena Anda telah membangun selimut cakupan pengujian sepanjang waktu.
c) Kode jadi akan jauh lebih baik sebagai hasilnya.
sumber
Apakah TDD benar-benar berfungsi untuk proyek yang kompleks?
Iya. Tidak setiap proyek jadi saya diberitahu bekerja dengan baik dengan TDD, tetapi sebagian besar aplikasi bisnis baik-baik saja, dan saya yakin yang tidak berfungsi dengan baik ketika mereka ditulis dengan cara TDD murni dapat ditulis dengan cara ATDD tanpa masalah besar.
Menghasilkan dan memelihara data tiruan
Jaga agar tetap kecil dan hanya memiliki apa yang Anda butuhkan dan ini tampaknya bukan masalah yang menakutkan. Jangan salah paham, itu menyakitkan. Tapi itu bermanfaat.
Menguji GUI.
Tes MVVM dan pastikan itu dapat diuji tanpa melihat. Saya menemukan ini tidak lebih sulit daripada menguji sedikit logika bisnis lainnya. Menguji tampilan dalam kode saya tidak lakukan, semua yang Anda uji namun pada saat ini adalah mengikat logika, yang satu harapan akan ditangkap dengan cepat ketika Anda melakukan tes manual cepat.
Menguji bisnis
Tidak ditemukan masalah. Banyak tes kecil. Seperti yang saya katakan di atas, beberapa kasus (pemecah teka-teki Sudoku tampaknya menjadi populer) tampaknya sulit untuk dilakukan TDD.
TDD mensyaratkan bahwa persyaratannya 100% benar.
Tidak, tidak. Dari mana Anda mendapatkan ide ini? Semua praktik Agile menerima bahwa persyaratan berubah. Anda perlu tahu apa yang Anda lakukan sebelum melakukannya, tetapi itu tidak sama dengan mengharuskan persyaratan menjadi 100%. TDD adalah praktik umum di Scrum, di mana persyaratan (Cerita Pengguna), menurut definisi, tidak 100% lengkap.
sumber
Pertama, saya percaya masalah Anda lebih tentang pengujian unit secara umum daripada TDD, karena saya tidak melihat apa pun yang benar-benar spesifik TDD (tes-pertama + siklus refactor merah-hijau) dalam apa yang Anda katakan.
Apa yang Anda maksud dengan data tiruan? Sebuah tiruan seharusnya hanya berisi hampir tidak ada data, yaitu tidak ada bidang selain satu atau dua yang dibutuhkan dalam pengujian, dan tidak ada dependensi selain sistem yang diuji. Menyiapkan nilai tiruan harapan atau nilai pengembalian dapat dilakukan dalam satu baris, jadi tidak ada yang mengerikan.
Jika maksud Anda database mengalami perubahan tanpa modifikasi yang tepat telah dibuat untuk model objek, pengujian unit baik tepat di sini untuk memperingatkan Anda tentang itu. Jika tidak, perubahan pada model harus tercermin dalam unit test dengan jelas, tetapi dengan indikasi kompilasi, hal itu mudah dilakukan.
Anda benar, unit menguji GUI (Tampilan) tidak mudah, dan banyak orang melakukannya dengan baik tanpa itu (selain itu, menguji GUI bukan bagian dari TDD). Sebaliknya, unit yang menguji Pengontrol / Presenter / ViewModel / lapisan menengah apa pun Anda sangat disarankan, sebenarnya itu adalah salah satu alasan utama pola seperti MVC atau MVVM.
Jika logika bisnis Anda rumit, biasanya unit test Anda sulit dirancang. Terserah kepada Anda untuk membuat mereka menjadi atomik mungkin, masing-masing menguji hanya satu tanggung jawab dari objek yang diuji. Tes unit semakin dibutuhkan dalam lingkungan yang kompleks karena mereka memberikan jaring keamanan yang menjamin bahwa Anda tidak melanggar aturan atau persyaratan bisnis saat Anda membuat perubahan pada kode.
Benar-benar tidak. Perangkat lunak yang berhasil mensyaratkan bahwa persyaratannya 100% benar;) Tes unit hanya mencerminkan visi Anda tentang persyaratan saat ini; jika visi tersebut cacat, kode Anda dan perangkat lunak Anda akan terlalu, unit test atau tidak ... Dan di situlah unit test bersinar: dengan judul tes yang cukup eksplisit, keputusan desain dan interpretasi persyaratan Anda menjadi transparan, yang membuatnya lebih mudah untuk menunjuk jari Anda pada apa yang perlu diubah saat pelanggan Anda berkata, "aturan bisnis ini tidak seperti yang saya inginkan".
sumber
Saya harus tertawa ketika mendengar seseorang mengeluh bahwa alasan mereka tidak dapat menggunakan TDD untuk menguji aplikasi mereka adalah karena aplikasi mereka sangat rumit. Apa alternatifnya? Apakah monyet uji menggedor pada hektar keyboard? Biarkan pengguna menjadi penguji? Apa lagi? Tentu saja sulit dan rumit. Apakah Anda pikir Intel tidak menguji chip mereka sampai mereka mengirim? Bagaimana "kepala di pasir" itu?
sumber
Saya telah menemukan TDD (dan pengujian unit secara umum) hampir tidak mungkin untuk alasan terkait: Kompleks, novel, dan / atau algoritma fuzzy. Masalah yang paling saya temui dalam prototipe penelitian yang saya tulis adalah bahwa saya tidak tahu apa jawaban yang benar selain dengan menjalankan kode saya. Terlalu rumit untuk mencari tahu dengan tangan untuk apa pun kecuali kasus-kasus sepele yang konyol. Ini terutama benar jika algoritma melibatkan heuristik, perkiraan, atau non-determinisme. Saya masih mencoba untuk menguji fungsionalitas tingkat bawah yang tergantung pada kode ini dan menggunakan sangat menegaskan sebagai pemeriksaan kewarasan. Metode pengujian terakhir saya adalah menulis dua implementasi yang berbeda, idealnya dalam dua bahasa yang berbeda menggunakan dua set pustaka yang berbeda dan membandingkan hasilnya.
sumber
Dari pengalaman saya: Ya untuk Unittests (uji modul / fitur secara terpisah) karena ini sebagian besar tidak memiliki masalah yang Anda sebutkan: (Gui, Mvvm, Business-Modell). Saya tidak pernah memiliki lebih dari 3 ejekan / bertopik untuk memenuhi satu unittest (tapi mungkin domain Anda membutuhkan lebih).
Namun saya tidak yakin apakah TDD dapat menyelesaikan masalah yang Anda sebutkan pada integrasi atau pengujian end-to-end dengan tes gaya BDD.
Namun setidaknya beberapa masalah bisa dikurangi .
Ini benar jika Anda ingin melakukan cakupan lengkap pada tingkat tes integrasi atau tes ujung ke ujung. Mungkin lebih mudah melakukan peliputan lengkap pada tingkat yang paling sederhana.
Contoh: Memeriksa izin pengguna yang kompleks
Menguji Fungsi
IsAllowedToEditCusterData()
pada tingkat uji integrasi akan perlu menanyakan objek yang berbeda untuk informasi tentang pengguna, domain, pelanggan, lingkungan .....Mengejek bagian-bagian ini cukup sulit. Ini terutama benar jika
IsAllowedToEditCusterData()
harus mengetahui objek yang berbeda ini.Pada Unittest-Level Anda akan memiliki Function
IsAllowedToEditCusterData()
yang mengambil contoh 20 parameter yang berisi semua fungsi yang perlu diketahui. KarenaIsAllowedToEditCusterData()
tidak perlu tahu bidang apa auser
, adomain
, acustomer
, .... memiliki ini mudah untuk diuji.Ketika saya harus mengimplementasikan
IsAllowedToEditCusterData()
saya memiliki dua kelebihan:Satu kelebihan yang tidak lebih dari mendapatkan 20 parameter tersebut dan kemudian memanggil kelebihan dengan 20 parameter yang melakukan pengambilan keputusan.
(Saya
IsAllowedToEditCusterData()
hanya memiliki 5 parameter dan saya membutuhkan 32 kombinasi berbeda untuk mengujinya sepenuhnya)Contoh
sumber
Jawaban yang menyedihkan adalah tidak ada yang benar-benar berfungsi untuk proyek kompleks besar!
TDD sebagus apa pun dan lebih baik daripada kebanyakan, tetapi TDD sendiri tidak akan menjamin kesuksesan dalam proyek besar. Namun itu akan meningkatkan peluang kesuksesan Anda. Terutama ketika digunakan dalam kombinasi dengan disiplin manajemen proyek lainnya (verifikasi persyaratan, kasus penggunaan, matriks keterlacakan persyaratan, penelusuran kode, dll.).
sumber
Ingat bahwa pengujian unit adalah spesifikasi yang dipaksakan . Ini sangat berharga dalam proyek yang kompleks. Jika basis kode lama Anda tidak memiliki tes untuk mendukungnya, tidak ada yang akan berani mengubah apa pun karena mereka akan takut merusak apa pun.
"Wtf. Mengapa cabang kode ini ada di sana? Tidak tahu, mungkin seseorang membutuhkannya, lebih baik meninggalkannya di sana daripada membuat marah orang lain ..." Seiring waktu proyek-proyek kompleks menjadi lahan sampah.
Dengan tes, siapa pun dapat dengan yakin mengatakan, "Saya telah membuat perubahan drastis, tetapi semua tes masih berlalu." Menurut definisi, dia tidak merusak apa pun. Ini mengarah pada proyek yang lebih gesit yang dapat berkembang. Mungkin salah satu alasan kita masih membutuhkan orang untuk mempertahankan COBOL adalah karena pengujian tidak populer sejak saat itu: P
sumber
Saya telah melihat sebuah proyek besar yang kompleks benar-benar gagal ketika TDD digunakan secara eksklusif, yaitu tanpa setidaknya mengatur dalam debugger / IDE. Data tiruan dan / atau tes terbukti tidak memadai. Data nyata klien Beta sensitif dan tidak dapat disalin atau dicatat. Jadi, tim pengembang tidak pernah bisa memperbaiki bug fatal yang bermanifestasi ketika menunjuk data nyata, dan seluruh proyek dihilangkan, semua orang dipecat, semuanya.
Cara untuk memperbaiki masalah ini adalah dengan menjalankannya di debugger di situs klien, hidup terhadap data nyata, melangkah melalui kode, dengan titik istirahat, variabel arloji, menonton memori, dll. Namun, tim ini, yang menganggap kode mereka cocok untuk menghiasi menara gading terbaik, dalam kurun waktu hampir satu tahun tidak pernah sekalipun meluncurkan aplikasi mereka. Itu mengejutkan saya.
Jadi, seperti semuanya, keseimbangan adalah kuncinya. TDD mungkin bagus tetapi tidak bergantung padanya secara eksklusif.
sumber
Saya kira begitu, lihat Test Driven Development benar-benar berfungsi
sumber
Jika kombinasi anggaran, persyaratan, dan keterampilan tim ada di kuadran ruang proyek, 'tinggalkan harapan semua yang masuk ke sini', maka menurut definisi, sangat mungkin proyek itu akan gagal.
Mungkin persyaratannya rumit dan tidak stabil, infrastrukturnya tidak stabil, tim junior dan dengan pergantian tinggi, atau arsiteknya bodoh.
Pada proyek TDD, gejala kegagalan yang akan datang ini adalah bahwa tes tidak dapat ditulis sesuai jadwal; Anda mencoba, hanya untuk menemukan 'itu akan mengambil ini panjang, dan kami hanya memiliki itu '.
Pendekatan lain akan menunjukkan gejala yang berbeda ketika gagal; paling umum pengiriman sistem yang tidak berfungsi. Politik dan kontrak akan menentukan apakah itu lebih disukai.
sumber
TDD
mungkin terdengar sebagai rasa sakit di muka tetapi dalam jangka panjang itu akan menjadi teman terbaik Anda, percayalahTDD
akan benar-benar membuat aplikasi dapat dipertahankan dan aman dalam jangka panjang.sumber