Apa yang saya kehilangan dengan mengadopsi desain yang digerakkan oleh tes?
Daftarkan hanya yang negatif; jangan mencantumkan manfaat yang ditulis dalam bentuk negatif.
unit-testing
testing
tdd
IanL
sumber
sumber
Jawaban:
Beberapa kerugian (dan saya tidak mengklaim tidak ada manfaat - terutama ketika menulis fondasi proyek - itu akan menghemat banyak waktu di akhir):
sumber
Jika Anda ingin melakukan TDD "nyata" (baca: uji dulu dengan langkah-langkah merah, hijau, refactor) maka Anda juga harus mulai menggunakan mengejek / bertopik, ketika Anda ingin menguji titik integrasi.
Ketika Anda mulai menggunakan mock, setelah beberapa saat, Anda akan ingin mulai menggunakan Dependency Injection (DI) dan wadah Inversion of Control (IoC). Untuk melakukan itu, Anda perlu menggunakan antarmuka untuk semuanya (yang memiliki banyak jebakan sendiri).
Pada akhirnya, Anda harus menulis lebih banyak kode, daripada hanya melakukannya dengan "cara lama biasa". Alih-alih hanya kelas pelanggan, Anda juga perlu menulis antarmuka, kelas tiruan, beberapa konfigurasi IoC dan beberapa tes.
Dan ingat bahwa kode tes juga harus dipelihara dan dirawat. Tes harus dapat dibaca seperti yang lainnya dan butuh waktu untuk menulis kode yang baik.
Banyak pengembang tidak begitu mengerti bagaimana melakukan semua ini dengan "cara yang benar". Tetapi karena semua orang memberi tahu mereka bahwa TDD adalah satu-satunya cara yang benar untuk mengembangkan perangkat lunak, mereka hanya mencoba yang terbaik yang mereka bisa.
Ini jauh lebih sulit daripada yang mungkin dipikirkan. Seringkali proyek yang dilakukan dengan TDD berakhir dengan banyak kode yang tidak ada yang benar-benar mengerti. Tes unit sering menguji hal yang salah, dengan cara yang salah. Dan tidak ada yang setuju bagaimana tes yang baik akan terlihat, bahkan guru yang disebut.
Semua tes itu membuat jauh lebih sulit untuk "mengubah" (berlawanan dengan refactoring) perilaku sistem Anda dan perubahan sederhana menjadi terlalu sulit dan memakan waktu.
Jika Anda membaca literatur TDD, selalu ada beberapa contoh yang sangat bagus, tetapi seringkali dalam aplikasi kehidupan nyata, Anda harus memiliki antarmuka pengguna dan database. Di sinilah TDD menjadi sangat sulit, dan sebagian besar sumber tidak menawarkan jawaban yang baik. Dan jika mereka melakukannya, itu selalu melibatkan lebih banyak abstraksi: benda tiruan, pemrograman ke antarmuka, pola MVC / MVP dll., Yang lagi-lagi membutuhkan banyak pengetahuan, dan ... Anda harus menulis lebih banyak kode.
Jadi berhati-hatilah ... jika Anda tidak memiliki tim yang antusias dan setidaknya satu pengembang berpengalaman yang tahu cara menulis tes yang baik dan juga tahu beberapa hal tentang arsitektur yang baik, Anda benar-benar harus berpikir dua kali sebelum turun ke jalan TDD .
sumber
Ketika Anda sampai pada titik di mana Anda memiliki sejumlah besar tes, mengubah sistem mungkin perlu menulis ulang beberapa atau semua tes Anda, tergantung pada yang mana yang menjadi tidak valid oleh perubahan. Ini bisa mengubah modifikasi yang relatif cepat menjadi yang sangat memakan waktu.
Selain itu, Anda mungkin mulai membuat keputusan desain berdasarkan TDD daripada prioritas desain yang sebenarnya bagus. Sementara Anda mungkin memiliki solusi yang sangat sederhana dan mudah yang tidak mungkin untuk menguji cara TDD menuntut, Anda sekarang memiliki sistem yang jauh lebih kompleks yang sebenarnya lebih rentan terhadap kesalahan.
sumber
if part of the system is covered by tests and they pass, then everything is fine (including design)
.Saya pikir masalah terbesar bagi saya adalah hilangnya BESAR waktu yang dibutuhkan "untuk masuk ke dalamnya". Saya masih sangat banyak pada awal perjalanan saya dengan TDD (Lihat blog saya untuk pembaruan petualangan pengujian saya jika Anda tertarik) dan saya benar-benar menghabiskan berjam - jam untuk memulai.
Butuh waktu lama untuk memasukkan otak Anda ke "mode pengujian" dan menulis "kode yang dapat diuji" adalah keterampilan itu sendiri.
TBH, dengan hormat saya tidak setuju dengan komentar Jason Cohen tentang mempublikasikan metode privat, bukan itu masalahnya. Saya tidak lagi membuat metode publik dengan cara baru saya bekerja daripada sebelumnya . Namun, hal itu melibatkan perubahan arsitektur dan memungkinkan Anda untuk "menyambungkan" modul kode untuk membuat segala sesuatu yang lain lebih mudah untuk diuji. Anda seharusnya tidak membuat internal kode Anda lebih mudah diakses untuk melakukan ini. Kalau tidak, kita kembali ke titik awal dengan segala sesuatu bersifat publik, di mana enkapsulasi dalam hal itu?
Jadi, singkatnya:
PS: Jika Anda ingin tautan ke positif, saya telah bertanya dan menjawab beberapa pertanyaan tentang itu, lihat profil saya .
sumber
Dalam beberapa tahun saya mempraktikkan Test Driven Development, saya harus mengatakan kerugian terbesarnya adalah:
Jual ke manajemen
Jual ke pengembang lain
Mempertahankan kode uji bersama dengan kode produksi Anda
Menulis tes sehingga Anda dapat menutupi semuanya (cakupan kode 100%)
Namun, dengan itu saya akan mengatakan bahwa manfaat TDD jauh lebih besar daripada negatif untuk ide sederhana bahwa jika Anda dapat mencapai serangkaian tes yang baik yang mencakup aplikasi Anda tetapi tidak terlalu rapuh sehingga satu perubahan menghancurkan semuanya, Anda akan dapat terus menambahkan fitur baru pada hari 300 proyek Anda seperti yang Anda lakukan pada hari 1. Ini tidak terjadi pada semua orang yang mencoba TDD berpikir itu adalah peluru ajaib untuk semua kode bug-ridden mereka, dan sehingga mereka berpikir itu dapat bekerja, titik.
Secara pribadi saya telah menemukan bahwa dengan TDD, saya menulis kode yang lebih sederhana, saya menghabiskan lebih sedikit waktu untuk berdebat apakah solusi kode tertentu akan berfungsi atau tidak, dan bahwa saya tidak takut mengubah baris kode apa pun yang tidak memenuhi kriteria yang ditetapkan oleh tim.
TDD adalah disiplin yang sulit untuk dikuasai, dan saya sudah melakukannya selama beberapa tahun, dan saya masih belajar teknik pengujian baru sepanjang waktu. Ini adalah investasi waktu yang sangat besar di muka, tetapi, dalam jangka panjang, keberlanjutan Anda akan jauh lebih besar daripada jika Anda tidak memiliki tes unit otomatis. Sekarang, andai saja atasan saya bisa memikirkan ini.
sumber
Pada proyek TDD pertama Anda, ada dua kerugian besar, waktu dan kebebasan pribadi
Anda kehilangan waktu karena:
Anda kehilangan kebebasan pribadi karena:
Semoga ini membantu
sumber
TDD mengharuskan Anda untuk merencanakan bagaimana kelas Anda akan beroperasi sebelum Anda menulis kode untuk lulus tes tersebut. Ini adalah plus dan minus.
Saya merasa sulit untuk menulis tes dalam "ruang hampa" - sebelum kode apa pun telah ditulis. Dalam pengalaman saya, saya cenderung tersandung tes saya setiap kali saya pasti memikirkan sesuatu saat menulis kelas saya yang saya lupa saat menulis tes awal saya. Maka saatnya untuk tidak hanya memperbaiki kelas saya, tetapi juga ujian saya. Ulangi ini tiga atau empat kali dan itu bisa membuat frustrasi.
Saya lebih suka menulis draf kelas saya terlebih dahulu kemudian menulis (dan memelihara) baterai unit test. Setelah saya memiliki konsep, TDD berfungsi dengan baik untuk saya. Misalnya, jika bug dilaporkan, saya akan menulis tes untuk mengeksploitasi bug itu dan kemudian memperbaiki kode sehingga tes berlalu.
sumber
Membuat prototipe bisa sangat sulit dengan TDD - ketika Anda tidak yakin jalan apa yang akan Anda ambil untuk solusi, menulis tes di muka bisa sulit (selain yang sangat luas). Ini bisa jadi menyebalkan.
Jujur saya tidak berpikir bahwa untuk "pengembangan inti" untuk sebagian besar proyek ada kelemahan nyata, meskipun; itu dibicarakan lebih banyak dari yang seharusnya, biasanya oleh orang-orang yang percaya kode mereka cukup baik sehingga mereka tidak perlu tes (tidak pernah ada) dan orang-orang yang hanya polos tidak dapat diganggu untuk menulisnya.
sumber
Nah, dan peregangan ini, Anda perlu men-debug tes Anda. Juga, ada biaya tertentu dalam waktu untuk menulis tes, meskipun kebanyakan orang setuju bahwa itu adalah investasi di muka yang terbayar selama masa pakai aplikasi dalam kedua waktu men-debug dan menjaga stabilitas.
Namun, masalah terbesar yang saya miliki secara pribadi adalah membangun disiplin untuk benar-benar menulis ujian. Dalam sebuah tim, terutama tim yang sudah mapan, mungkin sulit meyakinkan mereka bahwa waktu yang dihabiskan bermanfaat.
sumber
Jika tes Anda tidak terlalu menyeluruh, Anda mungkin jatuh ke dalam pengertian yang salah tentang "semuanya bekerja" hanya karena Anda lulus ujian. Secara teoritis jika tes Anda lulus, kode tersebut berfungsi; tetapi jika kita bisa menulis kode dengan sempurna pertama kali kita tidak perlu tes. Moral di sini adalah memastikan untuk melakukan pemeriksaan kewarasan sendiri sebelum memanggil sesuatu yang lengkap, jangan hanya mengandalkan tes.
Pada catatan itu, jika pemeriksaan kewarasan Anda menemukan sesuatu yang tidak diuji, pastikan untuk kembali dan menulis tes untuk itu.
sumber
Kelemahan dari TDD adalah bahwa hal itu biasanya terkait erat dengan metodologi 'Agile', yang tidak mementingkan dokumentasi sistem, melainkan pemahaman di balik mengapa tes 'harus' mengembalikan satu nilai spesifik daripada yang lain hanya berada di pengembang. kepala.
Segera setelah pengembang meninggalkan atau lupa alasan bahwa tes mengembalikan satu nilai tertentu dan bukan yang lain, Anda gagal. TDD baik-baik saja JIKA itu didokumentasikan secara memadai dan dikelilingi oleh dokumentasi yang dapat dibaca manusia (mis. Manajer runcing) yang dapat dirujuk dalam 5 tahun ketika dunia berubah dan aplikasi Anda juga perlu.
Ketika saya berbicara tentang dokumentasi, ini bukan uraian kode, ini adalah tulisan resmi yang ada di luar aplikasi, seperti kasus penggunaan dan informasi latar belakang yang dapat dirujuk oleh manajer, pengacara dan getah miskin yang harus memperbarui kode Anda pada tahun 2011.
sumber
Saya telah mengalami beberapa situasi di mana TDD membuat saya gila. Untuk beberapa nama:
Rawatan kasus uji:
Jika Anda berada di perusahaan besar, banyak kemungkinan Anda tidak harus menulis sendiri test case atau setidaknya sebagian besar ditulis oleh orang lain ketika Anda masuk ke perusahaan. Fitur aplikasi berubah dari waktu ke waktu dan jika Anda tidak memiliki sistem, seperti HP Quality Center, untuk melacaknya, Anda akan menjadi gila dalam waktu singkat.
Ini juga berarti bahwa itu akan mengambil anggota tim baru cukup waktu untuk mengambil apa yang terjadi dengan kasus-kasus uji. Pada gilirannya, ini dapat diterjemahkan menjadi lebih banyak uang yang dibutuhkan.
Kompleksitas uji otomatisasi:
Jika Anda mengotomatiskan beberapa atau semua kotak uji ke dalam skrip uji yang dapat dijalankan mesin, Anda harus memastikan skrip uji ini selaras dengan kotak uji manual yang sesuai dan sejalan dengan perubahan aplikasi.
Selain itu, Anda akan menghabiskan waktu untuk men-debug kode yang membantu Anda menangkap bug. Menurut pendapat saya, sebagian besar bug ini berasal dari kegagalan tim pengujian untuk mencerminkan perubahan aplikasi dalam skrip pengujian otomatisasi. Perubahan logika bisnis, GUI, dan hal-hal internal lainnya dapat membuat skrip Anda berhenti berjalan atau berjalan dengan tidak dapat diandalkan. Terkadang perubahannya sangat halus dan sulit dideteksi. Setelah semua skrip saya melaporkan kegagalan karena mereka mendasarkan perhitungan mereka pada informasi dari tabel 1 sementara tabel 1 sekarang tabel 2 (karena seseorang menukar nama objek tabel dalam kode aplikasi).
sumber
Masalah terbesar adalah orang-orang yang tidak tahu cara menulis unit test yang tepat. Mereka menulis tes yang saling bergantung (dan mereka bekerja sangat baik dengan Ant, tetapi tiba-tiba gagal ketika saya menjalankannya dari Eclipse, hanya karena mereka berjalan dalam urutan yang berbeda). Mereka menulis tes yang tidak menguji apa pun khususnya - mereka hanya men-debug kode, memeriksa hasilnya, dan mengubahnya menjadi tes, menyebutnya "test1". Mereka memperluas cakupan kelas dan metode, hanya karena akan lebih mudah untuk menulis unit test untuk mereka. Kode unit test mengerikan, dengan semua masalah pemrograman klasik (kopling berat, metode yang panjang 500 baris, nilai-nilai hard-kode, duplikasi kode) dan sangat sulit untuk dipertahankan. Untuk beberapa alasan aneh orang memperlakukan unit test sebagai sesuatu yang lebih rendah daripada kode "asli", dan mereka tidak t peduli tentang kualitas mereka sama sekali. :-(
sumber
Anda kehilangan banyak waktu yang dihabiskan untuk menulis tes. Tentu saja, ini mungkin disimpan pada akhir proyek dengan menangkap bug lebih cepat.
sumber
Kelemahan terbesar adalah bahwa jika Anda benar-benar ingin melakukan TDD dengan benar, Anda harus banyak gagal sebelum Anda berhasil. Mengingat berapa banyak perusahaan perangkat lunak yang bekerja (dolar per KLOC), Anda pada akhirnya akan dipecat. Bahkan jika kode Anda lebih cepat, lebih bersih, lebih mudah dirawat, dan memiliki lebih sedikit bug.
Jika Anda bekerja di perusahaan yang membayar Anda oleh KLOC (atau persyaratan yang diterapkan - bahkan jika tidak diuji) tinggal jauh dari TDD (atau ulasan kode, atau pemrograman pasangan, atau Integrasi Berkelanjutan, dll. Dll.).
sumber
Anda kehilangan kemampuan untuk mengatakan bahwa Anda "selesai" sebelum menguji semua kode Anda.
Anda kehilangan kemampuan untuk menulis ratusan atau ribuan baris kode sebelum menjalankannya.
Anda kehilangan kesempatan untuk belajar melalui debugging.
Anda kehilangan fleksibilitas untuk mengirimkan kode yang tidak Anda yakini.
Anda kehilangan kebebasan untuk memasangkan modul Anda dengan ketat.
Anda kehilangan pilihan untuk tidak menulis dokumentasi desain tingkat rendah.
Anda kehilangan stabilitas yang menyertai kode yang takut diubah oleh semua orang.
sumber
Saya menjawab kedua tentang waktu pengembangan awal. Anda juga kehilangan kemampuan untuk bekerja dengan nyaman tanpa keamanan tes. Saya juga dideskripsikan sebagai nutbar TDD, sehingga Anda dapat kehilangan beberapa teman;)
sumber
Itu dianggap lebih lambat. Jangka panjang itu tidak benar dalam hal kesedihan itu akan menyelamatkan Anda di jalan, tetapi Anda akan berakhir menulis lebih banyak kode sehingga bisa dibilang Anda menghabiskan waktu pada "pengujian bukan pengkodean". Ini argumen yang salah, tetapi Anda memang bertanya!
sumber
Pemfokusan ulang pada persyaratan yang sulit dan tidak terduga adalah kutukan konstan dari programmer. Pengembangan yang digerakkan oleh ujian memaksa Anda untuk fokus pada persyaratan duniawi yang sudah diketahui, dan membatasi pengembangan Anda pada apa yang telah dibayangkan.
Pikirkan tentang hal ini, Anda mungkin akan berakhir merancang kasus uji tertentu, sehingga Anda tidak akan menjadi kreatif dan mulai berpikir "itu akan keren jika pengguna bisa melakukan X, Y, dan Z". Oleh karena itu, ketika pengguna mulai bersemangat tentang kemungkinan kebutuhan keren X, Y, dan Z, desain Anda mungkin terlalu kaku pada kasus uji yang telah ditentukan, dan akan sulit untuk menyesuaikan.
Ini, tentu saja, adalah pedang bermata dua. Jika Anda menghabiskan seluruh waktu merancang untuk setiap yang dapat dibayangkan, dapat dibayangkan, X, Y, dan Z yang diinginkan seorang pengguna, Anda pasti tidak akan pernah menyelesaikan apa pun. Jika Anda menyelesaikan sesuatu, mustahil bagi siapa pun (termasuk diri Anda) untuk mengetahui apa yang Anda lakukan dalam kode / desain Anda.
sumber
Ini bisa sulit dan memakan waktu tes menulis untuk data "acak" seperti XML-feed dan basis data (tidak terlalu sulit). Saya telah menghabiskan beberapa waktu belakangan ini bekerja dengan feed data cuaca. Ini tes menulis yang cukup membingungkan untuk itu, setidaknya karena saya tidak memiliki terlalu banyak pengalaman dengan TDD.
sumber
Anda akan kehilangan kelas besar dengan banyak tanggung jawab. Anda juga kemungkinan akan kehilangan metode besar dengan banyak tanggung jawab. Anda mungkin kehilangan beberapa kemampuan untuk refactor, tetapi Anda juga akan kehilangan beberapa kebutuhan untuk refactor.
Jason Cohen mengatakan sesuatu seperti: TDD membutuhkan organisasi tertentu untuk kode Anda. Ini mungkin salah secara arsitektur; misalnya, karena metode pribadi tidak dapat dipanggil di luar kelas, Anda harus membuat metode non-pribadi untuk membuatnya dapat diuji.
Saya mengatakan ini menunjukkan abstraksi yang terlewatkan - jika kode pribadi benar-benar perlu diuji, mungkin harus di kelas yang terpisah.
Dave Mann
sumber
Anda harus menulis aplikasi dengan cara yang berbeda: yang membuatnya dapat diuji. Anda akan terkejut betapa sulitnya ini pada awalnya.
Beberapa orang menemukan konsep berpikir tentang apa yang akan mereka tulis sebelum mereka menulisnya terlalu keras. Konsep seperti mengejek bisa sulit untuk beberapa juga. TDD dalam aplikasi lawas bisa sangat sulit jika tidak dirancang untuk pengujian. TDD di sekitar kerangka kerja yang tidak ramah TDD juga bisa menjadi perjuangan.
TDD adalah keterampilan sehingga para junior devs mungkin berjuang pada awalnya (terutama karena mereka tidak diajarkan untuk bekerja dengan cara ini).
Secara keseluruhan meskipun kontra menjadi dipecahkan ketika orang menjadi terampil dan Anda akhirnya mengambil kode 'bau' dan memiliki sistem yang lebih stabil.
sumber
Butuh beberapa waktu untuk masuk ke dalamnya dan beberapa waktu untuk mulai melakukannya dalam sebuah proyek tapi ... Saya selalu menyesal tidak melakukan pendekatan Test Driven ketika saya menemukan bug konyol bahwa tes otomatis bisa menemukan sangat cepat. Selain itu, TDD meningkatkan kualitas kode.
sumber
sumber
Jawaban bagus semuanya. Saya akan menambahkan beberapa cara untuk menghindari sisi gelap TDD:
Saya telah menulis aplikasi untuk melakukan swa-uji sendiri secara acak. Masalah dengan menulis tes khusus adalah bahkan jika Anda menulis banyak dari mereka mereka hanya membahas kasus yang Anda pikirkan. Generator uji acak menemukan masalah yang tidak Anda pikirkan.
Seluruh konsep banyak unit test menyiratkan bahwa Anda memiliki komponen yang dapat masuk ke keadaan tidak valid, seperti struktur data yang kompleks. Jika Anda menjauh dari struktur data yang kompleks, ada jauh lebih sedikit untuk diuji.
Sejauh aplikasi Anda mengizinkannya, jangan desain yang bergantung pada urutan pemberitahuan yang tepat, acara dan efek samping. Mereka dapat dengan mudah dijatuhkan atau diacak sehingga mereka membutuhkan banyak pengujian.
sumber
TDD memerlukan organisasi tertentu untuk kode Anda. Ini mungkin tidak efisien atau sulit dibaca. Atau bahkan secara arsitektur salah; misalnya, karena
private
metode tidak dapat dipanggil di luar kelas, Anda harus membuat metode non-pribadi untuk membuatnya dapat diuji, yang hanya salah.Ketika kode berubah, Anda harus mengubah tes juga. Dengan refactoring, ini bisa menjadi pekerjaan ekstra.
sumber
Izinkan saya menambahkan bahwa jika Anda menerapkan prinsip-prinsip BDD ke proyek TDD, Anda dapat mengurangi beberapa kelemahan utama yang tercantum di sini (kebingungan, kesalahpahaman, dll.). Jika Anda tidak terbiasa dengan BDD, Anda harus membaca pengantar Dan North. Dia muncul konsep sebagai jawaban untuk beberapa masalah yang timbul dari penerapan TDD di tempat kerja. Pengenalan Dan ke BDD dapat ditemukan di sini .
Saya hanya membuat saran ini karena BDD membahas beberapa hal negatif ini dan bertindak sebagai penghenti kesenjangan. Anda akan ingin mempertimbangkan ini ketika mengumpulkan umpan balik Anda.
sumber
Anda harus memastikan tes Anda selalu terkini, saat Anda mulai mengabaikan lampu merah adalah saat tes menjadi tidak berarti.
Anda juga harus memastikan tes komprehensif, atau saat bug besar muncul, tipe manajemen pengap yang akhirnya Anda yakinkan untuk membiarkan Anda menghabiskan waktu menulis lebih banyak kode akan mengeluh.
sumber
Orang yang mengajar pengembangan tim lincah saya tidak percaya pada perencanaan, Anda hanya menulis sebanyak untuk persyaratan terkecil.
Moto-nya adalah refactor, refactor, refactor. Saya memahami bahwa refactor berarti 'tidak merencanakan ke depan'.
sumber
Waktu pengembangan bertambah: Setiap metode perlu pengujian, dan jika Anda memiliki aplikasi besar dengan dependensi, Anda perlu menyiapkan dan membersihkan data Anda untuk pengujian.
sumber