TDD dan Kontrol Versi

25

Saat ini saya belajar tentang TDD dan mencoba mempraktikkannya dalam proyek pribadi saya. Saya juga telah menggunakan kontrol versi secara luas pada banyak proyek ini. Saya tertarik pada interaksi kedua alat ini dalam alur kerja yang khas, terutama ketika sampai pada pepatah untuk menjaga komit kecil. Berikut adalah beberapa contoh yang muncul di pikiran:

  1. Saya memulai proyek baru dan menulis tes sederhana untuk membuat kelas yang belum ada. Haruskah saya melakukan tes sebelum menulis kelas meskipun tes bahkan tidak dikompilasi? Atau haruskah saya mematikan jumlah minimum kode yang diperlukan untuk mendapatkan tes untuk dikompilasi sebelum melakukan?

  2. Saya menemukan bug dan menulis tes untuk membuatnya kembali. Haruskah saya melakukan tes gagal atau menerapkan perbaikan bug dan kemudian melakukan?

Ini adalah dua contoh yang langsung terlintas dalam pikiran. Jangan ragu untuk memberikan contoh tambahan dalam jawaban Anda.

Edit:

Saya membuat asumsi dalam kedua contoh itu segera setelah menulis tes saya akan menulis kode untuk lulus ujian. Situasi lain mungkin juga muncul: Saya mengerjakan proyek menggunakan TDD selama beberapa jam tanpa melakukan. Ketika saya akhirnya membuat komitmen, saya ingin memecah pekerjaan saya menjadi potongan-potongan kecil. (Git membuat ini relatif mudah walaupun Anda hanya ingin melakukan beberapa perubahan dalam satu file.)

Ini berarti bahwa pertanyaan saya adalah tentang apa yang harus dilakukan dan tentang kapan harus berkomitmen.

Kode-Guru
sumber

Jawaban:

21

Haruskah saya melakukan tes sebelum menulis kelas meskipun tes bahkan tidak dikompilasi? Atau haruskah saya mematikan jumlah minimum kode yang diperlukan untuk mendapatkan tes untuk dikompilasi sebelum melakukan?

Tentu saja tidak. Anda harus menyelesaikan ujian dan kelas. Melakukan sesuatu 1 yang bahkan tidak kompilasi tidak masuk akal, dan tentunya akan membuat orang bekerja pada proyek yang sama marah kalau Anda melakukannya secara teratur.

Saya menemukan bug dan menulis tes untuk membuatnya kembali. Haruskah saya melakukan tes gagal atau menerapkan perbaikan bug dan kemudian melakukan?

Tidak, jangan melakukan tes yang gagal. Hukum LeBlanc menyatakan:

Nanti sama dengan tidak pernah.

dan tes Anda mungkin gagal untuk waktu yang lama. Lebih baik memperbaiki masalah segera setelah terdeteksi.

Juga, gaya pengembangan TDD memberitahu:

Pengembangan yang digerakkan oleh tes terus-menerus mengulangi langkah-langkah untuk menambahkan kasus uji yang gagal, melewati mereka, dan refactoring.

Jika Anda memeriksa tes gagal, itu berarti Anda tidak menyelesaikan siklus.


1 Ketika saya mengatakan komit, maksud saya benar-benar komit ke trunk (untuk pengguna git, dorong perubahan Anda, sehingga pengembang lain akan mendapatkannya).

BЈовић
sumber
4
"dan tentu saja akan membuat orang yang marah mengerjakan proyek yang sama jika" - seseorang yang tinggal di dunia SVN menggunakan GIT dan Anda tidak akan membuat orang marah
Mateusz
3
Saya pikir melakukan itu baik-baik saja setelah menulis tes, tapi jangan memaksakannya sampai Anda selesai.
Matsemann
4
@radarbob Apakah ini berlaku bahkan untuk DVCS di mana ada perbedaan antara melakukan dan mendorong? Saya bisa membayangkan situasi di mana saya membuat beberapa komit ke repositori git lokal saya di mana pada komit terakhir, build tidak rusak tetapi pada komit sementara mungkin.
Code-Guru
6
Tidak, jangan melakukan tes gagal. Tetapi salah satu poin TDD adalah tepatnya membuat tes gagal sebelum pengkodean. Jadi melakukan tes yang gagal masuk akal.
mouviciel
4
@ Code-Guru: Untuk DVCS, aturannya adalah: "Jangan komit kode rusak ke cabang yang orang lain tarik secara teratur". Jika orang lain tidak menarik dari repo lokal Anda, maka itu bisa dalam kondisi apa pun yang dapat Anda jalani.
Bart van Ingen Schenau
6

Haruskah saya melakukan tes sebelum menulis kelas meskipun tes bahkan tidak dikompilasi?

Tidak.

Haruskah saya melakukan tes gagal

Tidak.

Anda berbicara tentang dua paradigma di sini:

  1. pengembangan berbasis tes - yang tidak mengatakan apa-apa tentang melakukan kode. Memang, ini memberitahu Anda tentang cara menulis kode dan kapan Anda selesai. Jadi saya menganggap setiap 'selesai' sebagai kandidat untuk komit.
  2. pengembangan tangkas, khususnya: "melakukan awal dan sering" (yang tidak memerlukan TDD). Gagasan di baliknya adalah untuk memiliki integrasi awal dengan komponen lain dalam sistem dan dengan demikian mendapatkan umpan balik awal. Jika Anda berkomitmen dalam DVCS secara lokal, dan tidak mendorong, itu tidak ada artinya. Komitmen lokal hanya membantu pengembang untuk menyusun pekerjaan mereka.

Rekomendasi saya adalah: ikuti lingkaran TDD sampai kode Anda dikompilasi, tes Anda berwarna hijau dan Anda punya sesuatu untuk berkontribusi pada sistem. Oleh karena itu Anda harus memotong fitur Anda secara vertikal, misalnya untuk topeng UI baru tidak membuat seluruh formulir dan melakukan tanpa logika bisnis, melainkan menerapkan satu aspek kecil tetapi di frontend serta logika bisnis serta di lapisan kegigihan .

Untuk perbaikan bug besar, komit setelah setiap perbaikan (mis. Refactoring), bahkan jika bug belum diperbaiki. Tes harus berwarna hijau, dan kode harus dikompilasi.

Andy
sumber
5

Tentu saja Anda mulai dengan menggunakan kontrol sumber yang sehat seperti git.

Kemudian Anda dapat bekerja sesuka Anda, dan komit di setiap sudut - langkah atau langkah apa pun adalah permainan yang adil.

Lalu sebelum mendorong hal-hal yang Anda squash seluruh pekerjaan menjadi satu komit. Atau pasangan, pada titik-titik di mana semuanya berwarna hijau dan komposisinya masuk akal. Dan dorong komitmen yang masuk akal itu. Untuk banyak kasus, buat cabang yang Anda gabungkan dengan --no-ff.

Kontrol sumber bukan sistem pelacakan kerja atau sejarawan. Komit harus menyajikan delta yang masuk akal dan masuk akal, sedangkan negara checkout setidaknya akan menyusun. Intermediate dapat dipertahankan untuk sementara waktu untuk keperluan ulasan, tetapi begitu semuanya dianggap baik-baik saja, satu komit per fitur adalah adil.

Balog Pal
sumber
5

Adalah pemahaman saya tentang dunia bahwa seseorang berkomitmen untuk menandai suatu titik yang mungkin diinginkan untuk kembali. Titik di mana tes gagal (tetapi mengkompilasi) jelas merupakan salah satu poin tersebut. Jika saya berjalan ke arah yang salah mencoba membuat tes lulus, saya ingin dapat mengembalikan kode kembali ke titik awal dan coba lagi; Saya tidak bisa melakukan ini jika saya belum berkomitmen.

Gober1
sumber
Saya setuju dengan kamu. Saya lebih suka menggunakan cabang yang berbeda untuk mengikuti aturan "jangan merusak build" dan menggabungkan perubahan di bagasi hanya ketika tes berlalu.
Fil
5

Haruskah saya melakukan tes sebelum menulis kelas meskipun tes bahkan tidak dikompilasi?

Dengan SCM bercabang (saya melihat Anda menggunakan Git) Anda harus melakukan kapan pun Anda ingin titik cadangan ("Saya mengacaukan sesuatu; Saya akan mengatur ulang direktori kerja ke titik cadangan terakhir") atau ketika Anda memiliki versi stabil. Ketika Anda memiliki versi stabil (semua tes lulus), Anda juga harus mempertimbangkan menggabungkan cabang fitur saat ini ke cabang pengembangan utama Anda.

Atau haruskah saya mematikan jumlah minimum kode yang diperlukan untuk mendapatkan tes untuk dikompilasi sebelum melakukan?

Terserah Anda (git memberi Anda fleksibilitas untuk melakukan kapan pun Anda suka tanpa memengaruhi anggota tim Anda yang lain, atau kemampuan Anda untuk mengerjakan fitur yang berbeda). Pastikan Anda tidak memiliki beberapa fitur yang tidak lengkap (tidak berfungsi) di cabang yang sama secara bersamaan (maka mereka akan memblokir satu sama lain).

Saya menemukan bug dan menulis tes untuk membuatnya kembali. Haruskah saya melakukan tes gagal atau menerapkan perbaikan bug dan kemudian melakukan?

Saya biasanya membuat dua komit untuk itu, kecuali kode tes benar-benar kecil / sepele untuk ditulis.

Ini adalah dua contoh yang langsung terlintas dalam pikiran. Jangan ragu untuk memberikan contoh tambahan dalam jawaban Anda.

Edit:

Saya membuat asumsi dalam kedua contoh bahwa saya segera setelah menulis tes, saya akan menulis kode untuk lulus ujian.

Itu bisa menjadi asumsi yang salah. Jika Anda bekerja sendiri (proyek pribadi) tidak ada yang menghentikan Anda untuk selalu melakukan itu. Dalam salah satu proyek saya yang paling sukses (berkenaan dengan menjaga kualitas kode tinggi dan TDD selama pengembangan proyek) kami mendefinisikan tes kadang-kadang sebelum mengimplementasikannya (yaitu kita akan mengatakan "tes" test_FOO_with_null_first_parameter "sekarang didefinisikan sebagai fungsi kosong dan lakukan seperti itu) Kemudian kita akan mengambil sprint (atau setengah sprint) kadang-kadang sebulan kemudian, hanya untuk meningkatkan cakupan tes untuk modul. Karena kita sudah memiliki tes yang dinyatakan mudah untuk diperkirakan.

Situasi lain mungkin juga muncul: Saya mengerjakan proyek menggunakan TDD selama beberapa jam tanpa melakukan. Ketika saya akhirnya membuat komitmen, saya ingin memecah pekerjaan saya menjadi potongan-potongan kecil. (Git membuat ini relatif mudah bahkan jika Anda ingin hanya ingin melakukan beberapa perubahan dalam satu file.) Ini berarti bahwa pertanyaan saya adalah sebanyak apa yang harus dikomit seperti halnya kapan harus berkomitmen.

Saya akan mengatakan pasti berkomitmen untuk membuat poin cadangan . Ini bekerja sangat baik untuk pengujian eksplorasi ("Saya hanya akan menambahkan beberapa cetakan di seluruh basis kode, jalankan dan git reset --harduntuk menghapusnya ketika saya sudah selesai) dan untuk prototyping.

utnapistim
sumber
2
Hati-hati merekomendasikan git reset --hard. Ini adalah salah satu dari beberapa perintah di git yang akan menyebabkan Anda kehilangan pekerjaan.
gnash117
2

Dalam alur pekerjaan saya, bila memungkinkan saya melakukan pekerjaan yang tidak pasti pada cabang kontrol sumber pribadi. Jadi saya bisa mencoba, gagal, coba lagi jika perlu sampai berhasil, dan hanya komit ke proyek yang lebih besar ketika saya memiliki kode kerja yang sebenarnya.

Dari perspektif TDD, pertanyaan "apakah Anda memeriksa tes terlebih dahulu?" sepenuhnya tergantung pada kode yang sedang Anda kerjakan. Jika ini kode baru, Anda tidak perlu check-in sampai Anda memiliki sesuatu yang layak untuk di-check-in. Tetapi jika itu bug yang ditemukan di kode yang sudah dikompilasi atau dikirim, memeriksa dalam tes untuk mereproduksi bug, OLEH SAMPAINYA, layak untuk diperiksa. Terutama jika ini adalah akhir dari hari kerja, dan Anda akan meninggalkan kantor sebelum Anda memperbaikinya Kode.

(Tentu saja, jika toko Anda memiliki proses pembuatan otomatis yang mati jika ada unit-test gagal, Anda mungkin tidak ingin memeriksa dalam tes yang gagal sampai Anda memperbaiki bug. Tapi itu sepertinya cara yang aneh untuk bekerja, karena "temukan dan mendokumentasikan bug "dan" memperbaiki bug "dapat dilakukan oleh dua tim yang sepenuhnya berbeda.)

DougM
sumber