TDD, tes baru sementara yang lama belum diimplementasikan

13

Saya bereksperimen dengan pengembangan yang digerakkan oleh tes, dan saya menemukan bahwa saya sering datang ke situasi berikut:

  1. Saya menulis tes untuk beberapa fungsionalitas X. Tes-tes itu gagal.
  2. Ketika mencoba mengimplementasikan X, saya melihat bahwa saya perlu mengimplementasikan beberapa fitur Y di lapisan bawah kode saya. Begitu...
  3. Saya menulis tes untuk Y. Sekarang kedua tes untuk X dan Y gagal.

Suatu ketika saya memiliki 4 fitur di berbagai lapisan kode yang sedang dikerjakan pada saat yang sama, dan saya kehilangan fokus pada apa yang sebenarnya saya lakukan (terlalu banyak tes gagal pada saat yang sama).

Saya pikir saya bisa menyelesaikan ini dengan lebih berupaya merencanakan tugas saya bahkan sebelum saya mulai menulis tes. Tetapi dalam beberapa kasus saya tidak tahu bahwa saya harus masuk lebih dalam, karena misalnya saya tidak tahu API lapisan bawah dengan sangat baik.

Apa yang harus saya lakukan dalam kasus seperti itu? Apakah TDD punya rekomendasi?

liori
sumber

Jawaban:

9

Hal yang baik adalah Anda menyadari bahwa kode Anda sedang diuji membutuhkan bantuan. Daripada mengimplementasikannya segera, buat antarmuka dan gunakan tiruan untuk memastikan tes Anda menandai kode yang benar. Setelah melewati tes tersebut, Anda dapat melanjutkan untuk mengimplementasikan kode yang menjadi sandarannya.

Michael Brown
sumber
Tes saya biasanya tidak memiliki pengetahuan tentang apa yang harus dilakukan suatu metode secara internal (apa API tingkat rendah untuk memanggil). Haruskah saya menyesuaikan tes untuk mengejek apa pun yang saya butuhkan dalam kode yang diuji?
liori
2
Demikian pula, kelas yang Anda uji seharusnya tidak peduli apa yang 'lapisan bawah' lakukan. Gunakan tiruan / bertopik di tempat kelas / objek aktual. Ini mungkin memerlukan sedikit usaha lebih banyak dalam desain, tetapi menghasilkan kode yang kurang digabungkan dan lebih mudah untuk digunakan kembali.
Mchl
1
Apakah Anda menggunakan injeksi ketergantungan? Ini adalah bagaimana Anda dapat dengan mudah memisahkan masalah tingkat yang lebih rendah dari kelas tingkat yang lebih tinggi. Kelas Anda yang diuji memiliki konstruktor dengan parameter untuk dependensinya (sebagai antarmuka) dalam pengujian Anda membuat tiruan untuk antarmuka. Pada dasarnya Anda berpura-pura telah menerapkan layanan tingkat bawah.
Michael Brown
@ Mike Brown, ya, saya lakukan. Saya tahu saya bisa membuat benda tiruan. Tetapi kemudian dalam pengujian saya untuk fitur Xsaya harus tahu bagian mana dari dependensi yang Xperlu saya tiru. Saya merasa bahwa ini adalah bagian dari detail implementasi, yang seharusnya tidak menjadi bagian dari tes - jika tidak saya mungkin perlu mengubah tes saat refactoring implementasi. Haruskah saya khawatir tentang itu?
liori
1
Tidak sama sekali ... pengujian harus mencerminkan asumsi sistem yang diuji. Ini juga membantu Anda mengekspos apa yang Anda butuhkan dari layanan yang diandalkan sistem. Saya dulu setuju dengan Anda tentang masalah ini tetapi saya membandingkannya dengan bagaimana saya memahami pemrograman rekursif. Pertama Anda menulis kode dengan asumsi bahwa Anda memiliki fungsi yang melakukan apa yang Anda inginkan. Kemudian Anda menulis kode yang melakukan apa yang Anda inginkan.
Michael Brown
4

Rintisan dan tiruan dapat digunakan untuk mensimulasikan fungsi yang belum dimodifikasi / diimplementasikan. Mereka juga dapat membantu Anda menyelesaikan dependensi yang menyebabkan 'reaksi berantai' semacam ini.

Di sisi lain, mungkin hanya menyimpan satu (gagal) tes yang mendorong perubahan berikutnya adalah pendekatan terbaik.

Tes lain yang menargetkan kode yang bergantung pada fungsionalitas baru dapat dinonaktifkan sementara karena mereka tidak benar-benar relevan pada titik ini yaitu. dalam kasus Anda, nonaktifkan tes untuk X sampai Anda menerapkan Y dll.

Dengan begitu Anda bisa tetap fokus pada perubahan berikutnya hanya yang Anda inginkan, saya pikir.

ratkok
sumber
Ha, saya mencari fitur untuk mematikan tes selama uji coba di dalam IDE saya, dan belum menemukannya. Sekarang saya menemukan bahwa python unittestsudah melewati tes. Ini mungkin cukup bagiku.
liori
Kami menggunakan kerangka uji C ++ google test - dan memiliki opsi untuk menonaktifkan tes. Tes yang dinonaktifkan tidak dijalankan tetapi dikompilasi - saat Anda membutuhkannya - tes tersebut siap untuk dijalankan (selain itu Anda dapat 'memaksa eksekusi' tes yang dinonaktifkan - semacam 'run-time enable') - fitur unggulan ...
ratkok
3

Berhenti

Begitu saja sepertinya ada dua masalah terpisah di sini:

  1. Anda lupa beberapa cerita dan skenario pengujian, dan tidak menemukannya sampai Anda mulai mengerjakan skenario pengujian tertentu, dan / atau

  2. Anda benar-benar melakukan pengujian unit, dan bukan pengujian fitur TDD

Untuk # 1, berhenti , kembali, dan perbarui cerita dan uji skenario, kemudian mulai lagi dengan skenario yang berbeda.

Untuk # 2, berhentilah , dan ingat bahwa Anda sedang menguji fitur, bukan unit, jadi gunakan ejekan untuk mengabaikan antarmuka lain dan / atau menerapkan lebih banyak kode untuk membuat lulus uji tanpa menambahkan skenario pengujian baru. Ini mengasumsikan bahwa Anda tidak melewatkan skenario pengujian, tetapi sebaliknya - dan ini benar-benar umum - menggabungkan pengujian unit dan TDD.

Steven A. Lowe
sumber
Saya sangat menyukai jawaban Anda, ini menjelaskan lebih baik apa yang sebenarnya terjadi.
maple_shaft
... Dengan itu dikatakan saya tidak tahu seorang PM di dunia yang tidak akan benar-benar kehilangan pikirannya pada kalimat, "BERHENTI, kita perlu mundur". Mereka akan mencoba segalanya mengorbankan anak pertama mereka di altar untuk menjaga proyek tetap maju, hutang teknis dan tes unit tidak lengkap menjadi terkutuk. Saya kira Anda tidak dapat menyalahkan mereka ketika satu-satunya metrik mereka di suatu organisasi menyelesaikan proyek tepat waktu. Beberapa org hanya menghargai waktu daripada kualitas dan inilah sebabnya saya mungkin tidak pernah melihat TDD bekerja dengan sukses pada jenis organisasi ini, yang sayangnya PALING dari mereka IMO.
maple_shaft
@maple_shaft: jumlah waktu yang Anda hentikan untuk berkumpul kembali mungkin hanya beberapa jam - kecuali proses Anda jalan, jauh dari basis, dalam hal ini berhenti selama beberapa hari untuk mendapatkannya kembali ke jalurnya akan membuatnya jauh lebih mungkin bahwa proyek akan berhasil. Tidak ada gunanya pergi dengan kecepatan penuh di jalur yang salah!
Steven A. Lowe
0

Ini adalah pertanyaan yang bagus dan frustrasi besar bagi saya juga dengan TDD. Saya merasa seperti kekurangan TDD dalam skenario ini di mana Anda tidak memiliki cara untuk mengetahui komponen atau fitur tingkat rendah apa yang akan Anda butuhkan sampai Anda mulai berkembang.

Secara pribadi saya menemukan bahwa TDD hanya berfungsi jika Anda tahu persis apa yang perlu Anda lakukan dan apa yang perlu Anda panggil untuk melakukan fitur. Pengembang tidak selalu tahu segalanya sebelum kita mulai jadi saya telah menemukan bahwa cara terbaik bagi diri saya untuk mengurangi situasi yang Anda gambarkan:

Prototipe

Ketika saya membuat aplikasi prototipe sederhana untuk mengeksplorasi dan menemukan metode dan pendekatan untuk masalah teknis maka saya menemukan banyak pekerjaan kaki dan mendapatkan penelitian dari jalan sebelum saya mulai. Merancang dan memperkirakan menjadi jauh lebih mudah juga.

Jika prototipe harus terlibat sehingga menjadi aplikasi maka saya mendorong Anda untuk tidak melakukan hal yang malas namun dan membangun unit test untuk prototipe Anda setelah fakta.

Anda harus tahu lebih banyak tentang API tingkat lebih rendah pada saat itu dan dapat berhasil mengejek API tingkat lebih rendah di komponen level yang lebih tinggi.

maple_shaft
sumber
Jadi Anda sebenarnya menyarankan untuk mendapatkan lebih banyak informasi untuk tahap perencanaan dengan melakukan beberapa kode eksplorasi dalam cara informal (= tidak menggunakan beberapa metodologi formal). Dan kemudian berasumsi bahwa itu akan memberikan informasi yang cukup untuk merencanakan kode yang sebenarnya. Apakah saya benar?
liori
Mengapa Anda menganggap bahwa prototipe adalah proses informal? Setiap perkiraan harus memperhitungkan prototipe dan jadwal proyek harus memperhitungkannya serta tugas pengembangan yang diperlukan. Saya melihatnya sama dengan Desain atau Code-Review. Pada catatan itu IS itu diformalkan dan harus dipertanggungjawabkan, bahkan lebih pada tugas-tugas dengan banyak yang tidak diketahui. Tanpa prototyping dan kemampuan untuk melakukan Proof-of-Concept, maka mengejar TDD hanya mengasumsikan bahwa pengembang tahu SEMUANYA tentang APA SAJA dengan SEMUA fitur. Dunia nyata tidak bekerja seperti itu dan saya tidak peduli seberapa cerdas atau berpengalamannya Anda.
maple_shaft
Dengan "cara informal" saya tidak bermaksud bahwa waktu untuk membuat prototipe tidak boleh dipertanggungjawabkan, tetapi saat Anda melakukan prototipe, Anda tidak mengikuti TDD atau metodologi kode lainnya.
liori
TDD adalah metodologi untuk Unit Pengujian dan Pengembangan. Apakah masuk akal untuk melakukan TDD untuk Tinjauan Kode? Apakah TDD masuk akal untuk Desain, menulis Spesifikasi Teknis atau Papan Tulis? Prototyping adalah tugas itu sendiri, jenis pengembangan eksplorasi untuk penelitian, bukti konsep, dan pendidikan.
maple_shaft
1
TDD sangat masuk akal untuk membuat prototipe. Ini memungkinkan Anda untuk dengan cepat mengekspos hal-hal apa pun itu (objek, fungsi, API, seluruh program) dalam bentuk serangkaian persyaratan yang dapat diulang dan dapat dieksekusi. Bantulah diri Anda sendiri dan baca Perangkat Lunak Berorientasi Objek yang Dipandu oleh Tes ; itu akan membawa Anda selangkah demi selangkah membangun seluruh aplikasi (termasuk integrasi) dengan cara uji-pertama.
Frank Shearar
0

Tergantung tes apa yang Anda tulis saat mengerjakan TDD.

Model klasik adalah untuk menulis tes unit dan menggunakan tiruan atau bertopik untuk memisahkan tes dari "unit" kode lainnya.

Ada banyak model alternatif lain seperti ATDD di mana tes stack penuh, atau hampir stack test penuh. Dalam kasus khusus ini, tes penulisan Anda yang menegaskan perilaku program yang diperlukan bukan satu unit kode sehingga Anda tidak akan menulis tes lain. Anda akan mendapatkan implement pulang pergi untuk memenuhi tes. Anda kemudian menambahkan tes lain untuk fitur / perilaku lain.

dietbuddha
sumber