it-swarm-id.com

Apakah TDD benar-benar berfungsi untuk proyek yang kompleks?

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 dalam 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 ini bukan kasus dalam skenario yang rumit.

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?

53
Amir Rezaei

Sulit dan tidak realistis untuk mempertahankan data tiruan besar. Ini bahkan lebih sulit ketika struktur basis data mengalami perubahan.

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 kasus uji unit. Ini sangat sederhana, sungguh.

Ketika produk berevolusi, spreadsheet dari kasus uji diperbarui dan tes unit baru dihasilkan. Lakukan sepanjang waktu. Ini benar-benar berfungsi.

Bahkan dengan MVVM dan kemampuan untuk menguji GUI, dibutuhkan banyak kode untuk mereproduksi skenario GUI.

Apa? "Reproduksi"?

Maksud dari TDD adalah untuk Merancang hal-hal untuk Testability (Pengembangan Drive Test). Jika GUI 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.

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.

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 script sederhana Python 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 pengujian 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 rumit, para ahli harus menghasilkan contoh nyata dari proses tersebut.

TDD mensyaratkan bahwa persyaratannya 100% benar. Dalam kasus seperti itu, orang dapat berharap bahwa persyaratan yang bertentangan akan ditangkap selama pembuatan tes. Tapi masalahnya adalah ini bukan skenario yang kompleks.

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 dari kontradiksi sebelumnya dalam proses, jauh sebelum implementasi (dan argumen selama pengujian penerimaan pengguna).

Anda memiliki kode yang lulus beberapa tes dan gagal lainnya. Anda melihat hanya tes tersebut dan Anda menemukan kontradiksinya. Ini bekerja sangat, sangat baik dalam praktiknya karena sekarang pengguna harus berdebat tentang kontradiksi dan menghasilkan contoh yang konsisten dan konkret dari perilaku yang diinginkan.

52
S.Lott

Ya

Paparan pertama saya ke TDD bekerja pada 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 panitia. Tidak ada yang mengharapkan kesempurnaan dalam pengujian, tetapi semua fungsi yang terpapar secara publik harus memiliki setidaknya satu tes, dan begitu komponen diserahkan ke kontrol sumber, semua tes unit harus selalu lulus (bahkan jika mereka melakukannya karena komponen itu melaporkan secara salah 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 lulus uji unit. Sungguh mengherankan betapa cepatnya kualitas turun ke toilet, dan kemudian jadwal mengikutinya.

28
Bob Murphy

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.

18
Wyatt Barnett

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 bekerja 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
Uji MVVM dan pastikan yang 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 logika yang mengikat, yang satu harapan akan tertangkap 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 mengharuskan persyaratan 100% benar
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.

10
mlk

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.

Sulit dan tidak realistis untuk mempertahankan data tiruan besar.

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.

Ini bahkan lebih sulit ketika struktur basis data mengalami perubahan.

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.

Bahkan dengan MVVM dan kemampuan untuk menguji GUI, dibutuhkan banyak kode untuk mereproduksi skenario GUI.

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 Controller/Presenter/ViewModel/lapisan menengah apa pun Anda sangat disarankan, sebenarnya itu adalah salah satu alasan utama pola seperti MVC atau MVVM.

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.

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.

TDD mensyaratkan bahwa persyaratannya 100% benar.

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, uji unit atau tidak ... Dan di situlah tes unit 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".

9
guillaume31

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?

6
SnoopDougieDoug
> Does TDD really work for complex projects?

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 bukan shure jika TDD dapat menyelesaikan masalah yang Anda sebutkan pada integrasi atau pengujian end-to-end dengan tes gaya BDD.

Tapi setidaknya beberapa masalah dapat dikurangi.

> However complex business logic is hard to test since the number 
> of combinations of tests (test space) is very large.

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 perlu meminta 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. Karena IsAllowedToEditCusterData() tidak perlu tahu bidang apa a user, a domain, a customer, .... memiliki ini mudah untuk diuji.

Ketika saya harus mengimplementasikan IsAllowedToEditCusterData() saya mengalami dua kelebihan:

Satu kelebihan yang tidak lebih dari mendapatkan 20 parameter tersebut dan kemudian memanggil kelebihan dengan 20 parameter yang melakukan pengambilan keputusan.

(my IsAllowedToEditCusterData() hanya memiliki 5 parameter dan saya membutuhkan 32 kombinasi berbeda untuk mengujinya sepenuhnya)

Contoh

// method used by businesslogic
// difficuilt to test because you have to construct
// many dependant objects for the test
public boolean IsAllowedToEditCusterData() {
    Employee employee = getCurrentEmployee();
    Department employeeDepartment = employee.getDepartment();
    Customer customer = getCustomer();
    Shop shop = customer.getShop();

    // many more objects where the permittions depend on

    return IsAllowedToEditCusterData(
            employee.getAge(),
            employeeDepartment.getName(),
            shop.getName(),
            ...
        );
}

// method used by junittests
// much more easy to test because only primitives
// and no internal state is needed
public static boolean IsAllowedToEditCusterData(
        int employeeAge,
        String employeeDepartmentName,
        String shopName,
        ... ) 
{
    boolean isAllowed; 
    // logic goes here

    return isAllowed;
}
4
k3b

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 menjadi sandaran kode ini dan menggunakan pernyataan tegas saat memeriksa 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.

4
dsimcha

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.).

3
James Anderson

Saya telah melihat sebuah proyek besar yang kompleks benar-benar gagal ketika TDD digunakan secara eksklusif, yaitu tanpa setidaknya menyiapkan 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 akan pernah bisa memperbaiki bug fatal yang bermanifestasi ketika diarahkan ke data nyata, dan seluruh proyek dibatalkan, 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 baik tetapi jangan mengandalkannya secara eksklusif.

1
SPA

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

1
kizzx2

Jika kombinasi anggaran, persyaratan, dan keterampilan tim ada dalam kuadran ruang proyek, 'tinggalkan harapan semua yang masuk ke sini', maka menurut definisi, sangat besar kemungkinan proyek 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 memakan waktu ini lama, dan kami hanya punya it'.

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.

0
soru

Saya kira begitu, lihat Test Driven Development benar-benar berfungsi

Pada 2008, Nachiappan Nagappan, E. Michael Maximilien, Thirumalesh Bhat, dan Laurie Williams menulis makalah yang disebut “Menyadari peningkatan kualitas melalui pengembangan yang digerakkan oleh tes: hasil dan pengalaman empat tim industri“ (tautan PDF). Abstrak:

Test-driven development (TDD) adalah praktik pengembangan perangkat lunak yang telah digunakan secara sporadis selama beberapa dekade. Dengan praktik ini, seorang insinyur perangkat lunak melakukan siklus menit per menit antara penulisan unit gagal tes dan penulisan kode implementasi untuk lulus tes tersebut. Pengembangan yang digerakkan oleh tes baru-baru ini muncul kembali sebagai praktik penting yang memungkinkan dari metodologi pengembangan perangkat lunak tangkas. Namun, sedikit bukti empiris yang mendukung atau membantah kegunaan praktik ini dalam konteks industri. Studi kasus dilakukan dengan tiga tim pengembangan di Microsoft dan satu di IBM yang telah mengadopsi TDD. Hasil studi kasus menunjukkan bahwa kepadatan cacat pra-rilis dari empat produk menurun antara 40% dan 90% relatif terhadap proyek serupa yang tidak menggunakan praktik TDD. Subyektif, tim mengalami peningkatan 15-35% dalam waktu pengembangan awal setelah mengadopsi TDD.

Pada 2012, Ruby pada Rails praktik pengembangan mengasumsikan TDD. Saya pribadi mengandalkan alat seperti rspec untuk menulis tes dan ejekan, factory_girl untuk membuat objek, capybara untuk browser otomatisasi, simplecov untuk cakupan kode dan penjaga untuk mengotomatisasi tes ini.

Sebagai hasil dari menggunakan metodologi ini dan alat-alat ini, saya cenderung setuju secara subyektif dengan Nagappan dkk ...

0
Hiltmon