Saya memahami pengembangan yang digerakkan oleh tes sejauh ini sehingga Anda hanya diperbolehkan menulis kode produktif ketika Anda memiliki tes unit yang gagal (merah). Berdasarkan hal ini saya memiliki pertanyaan apakah pendekatan yang digerakkan oleh tes juga dapat diterapkan pada bentuk tes lainnya.
41
Jawaban:
Yang Anda butuhkan dari TDD adalah Anda menulis tes yang gagal, lalu memodifikasi kode Anda agar lulus.
Biasanya "tes unit" kecil dan cepat dan menguji beberapa bagian dari kode Anda secara terpisah. Karena mereka cepat, itu membuat loop merah / hijau / refactor juga cepat. Namun, mereka hanya menderita bagian pengujian dalam isolasi. Jadi Anda perlu tes lain juga (integrasi, penerimaan dll). Ini masih merupakan praktik yang baik untuk mengikuti prinsip yang sama: menulis tes gagal, lalu memodifikasi kode untuk membuatnya berfungsi. Perlu diketahui bahwa mereka biasanya lebih lambat, sehingga dapat mempengaruhi waktu siklus merah / hijau / refactor.
sumber
Siklus refactor merah hijau dibangun di atas satu prinsip yang sangat kuat:
Hanya uji kepercayaan yang Anda lihat lulus dan gagal.
Ya itu berfungsi dengan tes integrasi otomatis juga. Juga tes manual. Heck, itu bekerja pada penguji aki mobil. Inilah cara Anda menguji tes.
Beberapa orang menganggap unit test mencakup hal terkecil yang dapat diuji. Beberapa orang memikirkan sesuatu yang cepat untuk diuji. TDD lebih dari sekedar siklus refactor merah hijau tetapi bagian itu memiliki serangkaian tes yang sangat spesifik: Ini bukan tes yang idealnya Anda jalankan sekali sebelum mengirimkan kumpulan perubahan. Ini adalah tes yang akan Anda jalankan setiap kali Anda membuat perubahan. Bagi saya, itu adalah unit test Anda.
sumber
Ya, dan pendekatan terkenal yang melakukan ini adalah pengembangan yang didorong oleh Perilaku . Tes yang dihasilkan dari spesifikasi formal dalam BDD mungkin disebut "tes unit", tetapi biasanya tidak setingkat seperti pada TDD nyata, mereka mungkin akan lebih cocok dengan istilah "tes penerimaan".
sumber
Tidak. Anda hanya diperbolehkan menulis kode sesederhana mungkin untuk mengubah pesan tes. Itu tidak mengatakan apa-apa tentang tes seperti apa.
Bahkan, Anda mungkin akan mulai dengan menulis tes penerimaan gagal (merah) untuk kriteria penerimaan, lebih tepatnya, Anda menulis tes penerimaan paling sederhana yang mungkin gagal; setelah itu Anda menjalankan tes, melihatnya gagal, dan memverifikasi bahwa itu gagal karena alasan yang tepat. Kemudian Anda menulis tes fungsional yang gagal untuk sepotong fungsionalitas kriteria penerimaan itu, sekali lagi, Anda menulis tes fungsional paling sederhana yang mungkin gagal, menjalankannya, menontonnya gagal, dan memverifikasi bahwa itu gagal karena alasan yang tepat. Kemudian Anda menulis tes unit gagal, tes unit paling sederhana yang mungkin gagal, jalankan melihatnya gagal, verifikasi bahwa itu gagal karena alasan yang tepat.
Sekarang , Anda menulis kode produksi paling sederhana yang dapat mengubah pesan kesalahan. Jalankan pengujian lagi, verifikasi bahwa pesan kesalahan telah berubah, bahwa itu berubah ke arah yang benar, dan bahwa kode itu mengubah pesan untuk alasan yang benar. (Idealnya, pesan kesalahan harus hilang sekarang, dan tes harus lulus, tetapi lebih sering daripada tidak, lebih baik untuk mengambil langkah kecil mengubah pesan daripada mencoba untuk mendapatkan tes untuk lulus dalam sekali jalan - itulah alasannya mengapa pengembang kerangka kerja uji coba menghabiskan begitu banyak upaya untuk pesan kesalahan mereka!)
Setelah tes unit berhasil, Anda memperbaiki kode produksi Anda di bawah perlindungan pengujian Anda. (Perhatikan bahwa saat ini, tes penerimaan dan tes fungsional masih gagal, tetapi tidak apa-apa, karena Anda hanya refactoring unit individual yang dicakup oleh tes unit.)
Sekarang Anda membuat tes unit berikutnya dan ulangi di atas, sampai tes fungsional juga berlalu. Di bawah perlindungan uji fungsional, kini Anda dapat melakukan refactor di beberapa unit.
Siklus tengah ini sekarang berulang hingga tes penerimaan berlalu, pada titik mana Anda sekarang dapat melakukan refactor di seluruh sistem.
Sekarang, Anda memilih kriteria penerimaan berikutnya dan siklus luar dimulai lagi.
Kent Beck, "penemu" dari TDD (dia tidak suka istilah "penemu", katanya orang telah melakukan ini selama ini, dia hanya memberi nama dan menulis buku tentang itu) menggunakan analogi dari fotografi dan menyebutnya "memperbesar dan memperkecil".
Catatan: Anda tidak selalu membutuhkan tiga tingkat tes. Mungkin, terkadang Anda membutuhkan lebih banyak. Lebih sering, Anda membutuhkan lebih sedikit. Jika kepingan fungsionalitas Anda kecil, dan uji fungsional Anda cepat, maka Anda bisa bertahan tanpa (atau dengan tes unit lebih sedikit). Seringkali, Anda hanya perlu tes penerimaan dan tes unit. Atau, kriteria penerimaan Anda sangat halus sehingga tes penerimaan Anda adalah tes fungsional.
Kent Beck mengatakan bahwa jika dia memiliki tes fungsional yang cepat, kecil, dan fokus, dia pertama-tama akan menulis unit test, biarkan unit test mengemudikan kode, kemudian hapus (beberapa) unit test lagi yang mencakup kode yang juga tercakup oleh tes fungsional cepat. Ingat: kode uji juga kode yang perlu dipertahankan dan dire-refored, semakin sedikit, semakin baik!
Anda tidak benar-benar menerapkan TDD pada tes. Anda menerapkannya pada seluruh proses pengembangan Anda. Itulah yang dimaksud dengan "didorong" dari Test- Driven -Development: semua pengembangan Anda didorong oleh tes. Tes tidak hanya mengarahkan kode yang Anda tulis, tetapi juga mengarahkan kode apa yang akan ditulis, kode mana yang akan ditulis selanjutnya. Mereka menggerakkan desain Anda. Mereka memberi tahu Anda ketika Anda selesai. Mereka memberi tahu Anda apa yang harus dikerjakan selanjutnya. Mereka memberi tahu Anda tentang cacat desain dalam kode Anda (ketika tes sulit untuk menulis).
Keith Braithwaite telah menciptakan latihan yang dia sebut TDD As If You Meant It . Ini terdiri dari seperangkat aturan (berdasarkan Tiga Aturan TDD Paman Bob Martin , tetapi jauh lebih ketat) yang harus Anda ikuti dengan ketat dan yang dirancang untuk mengarahkan Anda untuk menerapkan TDD dengan lebih ketat. Ini bekerja paling baik dengan pemrograman pasangan (sehingga pasangan Anda dapat memastikan Anda tidak melanggar aturan) dan seorang instruktur.
Aturannya adalah:
Aturan-aturan ini dimaksudkan untuk melakukan TDD. Mereka tidak dimaksudkan untuk benar-benar melakukan TDD dalam produksi (meskipun tidak ada yang menghentikan Anda untuk mencobanya). Mereka bisa merasa frustasi karena kadang-kadang akan tampak seolah-olah Anda membuat ribuan langkah kecil mungil tanpa membuat kemajuan nyata.
sumber
TDD sama sekali tidak terbatas pada apa yang oleh komunitas pengujian Perangkat Lunak tradisional disebut "unit testing". Kesalahpahaman yang sangat umum ini adalah akibat kelebihan muatan Kent Beck yang tidak menguntungkan dari istilah "unit" ketika menggambarkan praktiknya tentang TDD. Yang dia maksud dengan "unit test" adalah tes yang berjalan secara terpisah. Itu tidak tergantung pada tes lain. Setiap tes harus mengatur keadaan yang dibutuhkan dan melakukan pembersihan ketika selesai. Dalam pengertian ini bahwa unit test dalam arti TDD adalah unit. Itu mandiri. Itu dapat berjalan dengan sendirinya atau dapat dijalankan bersama dengan tes unit lain dalam urutan apa pun.
Referensi : "Pengembangan Didorong oleh Contoh", oleh Kent Beck
Kent Beck menjelaskan apa yang dia maksud dengan “unit test” di Bab 32 - Menguasai TDD
sumber
Saya belum membaca buku-buku tentang itu, saya juga tidak sepenuhnya mengikuti praktik TDD "standar" sepanjang waktu, tetapi dalam pikiran saya poin utama dari filosofi TDD, yang saya sepenuhnya setujui, adalah bahwa Anda harus mendefinisikan kesuksesan terlebih dahulu . Ini penting di setiap tingkat desain, dari "Apa tujuan proyek ini?" untuk "Bagaimana seharusnya input dan output dari metode kecil ini?"
Ada banyak cara untuk melakukan definisi kesuksesan ini. Yang berguna, terutama untuk metode tingkat rendah dengan banyak kasus tepi, adalah menulis tes dalam kode. Untuk beberapa tingkat abstraksi, akan bermanfaat jika hanya menuliskan catatan singkat tentang tujuan modul atau apa pun, atau bahkan hanya memeriksa diri sendiri secara mental (atau bertanya pada rekan kerja) untuk memastikan semuanya masuk akal dan ada dalam tempat yang logis. Kadang-kadang membantu untuk menjelaskan tes integrasi dalam kode (dan tentu saja yang membantu seseorang untuk mengotomatiskannya), dan kadang-kadang membantu hanya dengan menentukan rencana pengujian cepat yang masuk akal yang dapat Anda gunakan untuk memastikan semua sistem bekerja sama dengan cara Anda mengharapkan.
Tetapi terlepas dari teknik atau alat khusus yang Anda gunakan, dalam pikiran saya hal utama untuk mengambil dari filosofi TDD adalah bahwa mendefinisikan kesuksesan terjadi terlebih dahulu. Kalau tidak, Anda melempar panah dan melukis bullseye di mana pun itu mendarat.
sumber
Dalam pembicaraan Test-Driven Development: Ini bukan apa yang kami maksud Steve Freeman menunjukkan slide berikut dari gambaran besar TDD (lihat gambar di bawah ini). Ini termasuk langkah "Tulis tes ujung-ke-ujung yang gagal" yang diikuti oleh "Tulis unit-gagal". (Klik untuk memperbesar, ini ada di kanan atas)
Jadi tidak dalam TDD, tes tidak selalu merupakan unit-tes.
Dan ya Anda bisa (dan mungkin harus) mulai dengan tes end-to-end tingkat tinggi yang gagal sebelum Anda menulis unit-test pertama Anda. Tes ini menjelaskan perilaku yang ingin Anda capai. Ini menghasilkan cakupan pada lebih banyak level piramida uji . Adrian Sutton menjelaskan pengalaman LMAX yang menunjukkan bahwa tes ujung ke ujung dapat memainkan peran besar dan berharga .
sumber
Tidak, itu tidak dapat diterapkan pada jenis tes lain, karena alasan praktis sederhana: jenis tes lain terlalu lama untuk dijalankan.
Siklus TDD yang umum adalah: tes gagal tulis, implementasikan, kode refactor. Langkah-langkah di antaranya adalah membangun dan melaksanakan tes, dan ini harus cepat kilat. Jika tidak, maka orang akan mulai melewatkan langkah-langkah, dan kemudian Anda tidak melakukan TDD lagi.
sumber