Saya cukup baru untuk TDD dan saya mengalami kesulitan saat membuat tes pertama ketika datang sebelum salah satu kode implementasi. Tanpa kerangka kerja untuk kode implementasi saya bebas untuk menulis tes pertama saya namun saya ingin tetapi sepertinya selalu tercemar oleh cara berpikir Java / OO saya tentang masalah.
Sebagai contoh di Github ConwaysGameOfLifeExample saya tes pertama yang saya tulis (rule1_zeroNeighbours) saya mulai dengan membuat objek GameOfLife yang belum diimplementasikan; disebut metode set yang tidak ada, metode langkah yang tidak ada, metode get yang tidak ada, dan kemudian gunakan pernyataan.
Tes berkembang ketika saya menulis lebih banyak tes dan refactored, tapi awalnya terlihat seperti ini
@Test
public void rule1_zeroNeighbours()
{
GameOfLife gameOfLife = new GameOfLife();
gameOfLife.set(1, 1, true);
gameOfLife.step();
assertEquals(false, gameOfLife.get(1, 1));
}
Ini terasa aneh karena saya memaksakan desain implementasi berdasarkan bagaimana saya telah memutuskan pada tahap awal ini untuk menulis tes pertama ini.
Dalam cara Anda memahami TDD apakah ini ok? Saya tampaknya mengikuti prinsip-prinsip TDD / XP di mana tes dan implementasi saya berkembang seiring waktu dengan refactoring, dan jadi jika desain awal ini terbukti tidak berguna itu akan terbuka untuk berubah, tetapi rasanya seperti saya memaksakan arah pada solusi dengan memulai dengan cara ini.
Bagaimana lagi orang menggunakan TDD? Saya bisa melewati iterasi refactoring dengan memulai tanpa objek GameOfLife, hanya primitif dan metode statis tapi itu sepertinya terlalu dibuat-buat.
sumber
Jawaban:
Saya pikir ini adalah poin kunci dalam pertanyaan Anda, Apakah ini diinginkan atau tidak tergantung pada apakah Anda condong ke ide codeninja bahwa Anda harus merancang di muka kemudian menggunakan TDD untuk mengisi implementasi, atau gagasan durron bahwa tes harus dilibatkan dalam mengusir desain serta implementasinya.
Saya pikir yang mana yang Anda sukai (atau di mana Anda jatuh di tengah) adalah sesuatu yang perlu Anda temukan sendiri sebagai preferensi. Sangat berguna untuk memahami pro dan kontra dari setiap pendekatan. Mungkin ada banyak, tetapi saya akan mengatakan yang utama adalah:
Desain Awal Pro
Desain Uji-Mengemudi Pro
Dengan membangun implementasi Anda di sekitar klien kode Anda (tes Anda), Anda mendapatkan kepatuhan YAGNI secara gratis, selama Anda tidak mulai menulis kasus uji yang tidak dibutuhkan. Secara umum, Anda mendapatkan API yang dirancang untuk digunakan oleh konsumen, yang pada akhirnya itulah yang Anda inginkan.
Gagasan menggambar sekelompok diagram UML sebelum menulis kode apa pun kemudian hanya mengisi celah itu bagus, tetapi jarang realistis. Dalam Code Complete Steve McConnell, desain terkenal digambarkan sebagai "masalah jahat" - masalah yang tidak dapat Anda pahami sepenuhnya tanpa terlebih dahulu setidaknya sebagian menyelesaikannya. Pasangkan ini dengan fakta bahwa masalah yang mendasarinya sendiri dapat berubah melalui perubahan persyaratan, dan model desain ini mulai merasa sedikit putus asa. Tes mengemudi memungkinkan Anda untuk hanya menggigit satu potong pekerjaan pada waktu-dalam desain, bukan hanya implementasi- dan tahu bahwa setidaknya untuk umur berubah menjadi hijau, tugas itu akan tetap up to date dan relevan.
Adapun contoh khusus Anda, seperti yang dikatakan durron, jika Anda memang menggunakan pendekatan mengusir desain dengan menulis tes paling sederhana, menggunakan antarmuka minimal, Anda mungkin akan mulai dengan antarmuka yang lebih sederhana daripada yang ada di cuplikan kode Anda .
sumber
Untuk dapat menulis tes di tempat pertama, Anda harus merancang API yang kemudian akan Anda implementasikan. Anda sudah memulai dengan langkah yang salah dengan menulis tes Anda untuk membuat seluruh
GameOfLife
objek dan menggunakannya untuk mengimplementasikan tes Anda.Dari Pengujian Unit Praktis dengan JUnit dan Mockito :
Tes Anda tidak banyak berupaya untuk merancang API. Anda telah mengatur sistem stateful di mana semua fungsi terkandung dalam
GameOfLife
kelas luar .Jika saya menulis aplikasi ini, sebagai gantinya saya akan memikirkan potongan yang ingin saya buat. Sebagai contoh, saya mungkin membuat
Cell
kelas, menulis tes untuk itu, sebelum pindah ke aplikasi yang lebih besar. Saya pasti akan membuat kelas untuk struktur data "tak terbatas di setiap arah" yang diperlukan untuk mengimplementasikan Conway dengan benar, dan mengujinya. Setelah semua itu selesai, saya akan berpikir tentang menulis kelas keseluruhan yang memilikimain
metode dan sebagainya.Sangat mudah untuk mengabaikan langkah "tulis tes yang gagal". Tetapi menulis tes gagal yang berfungsi seperti yang Anda inginkan adalah inti dari TDD.
sumber
boolean
, yang desain pasti akan lebih buruk untuk kinerja. Kecuali jika perlu diperluas di masa depan ke automata seluler lainnya dengan lebih dari dua negara?Ada aliran pemikiran yang berbeda tentang hal ini.
Ada yang mengatakan: tes tidak mengkompilasi adalah kesalahan - perbaiki tulis kode produksi terkecil yang tersedia.
Some Say: Tidak apa-apa untuk menulis tes pertama periksa apakah itu menyebalkan (atau tidak) semut kemudian membuat kelas / metode yang hilang
Dengan pendekatan pertama Anda benar-benar dalam siklus merah-hijau-refactor. Dengan yang kedua Anda memiliki gambaran umum yang sedikit lebih luas tentang apa yang ingin Anda capai.
Terserah Anda untuk memilih cara kerja Anda. IMHO kedua pendekatan itu valid.
sumber
Bahkan ketika saya mengimplementasikan sesuatu dengan cara "hack it together", saya masih memikirkan kelas dan langkah-langkah yang akan terlibat dalam keseluruhan program. Jadi Anda sudah memikirkan ini dan menulis pemikiran desain ini sebagai tes pertama - itu hebat!
Sekarang tetap iterasi melalui kedua implementasi untuk memenuhi tes awal ini, dan kemudian tambahkan lebih banyak tes untuk meningkatkan dan memperluas desain.
Apa yang mungkin membantu Anda adalah menggunakan Timun atau sejenisnya untuk menulis tes Anda.
sumber
Sebelum Anda mulai menulis tes Anda, Anda harus memikirkan bagaimana merancang sistem Anda. Anda harus meluangkan banyak waktu selama fase desain Anda. Jika Anda melakukannya, Anda tidak akan mendapatkan kebingungan tentang TDD ini.
TDD hanyalah tautan pendekatan pengembangan : TDD
1. Tambahkan tes
2. Jalankan semua tes dan lihat apakah yang baru gagal
3. Tulis beberapa kode
4. Jalankan tes
5. Kode refactor
6. Ulangi
TDD membantu Anda untuk mencakup semua fitur yang diperlukan apa yang telah Anda rencanakan sebelum mulai mengembangkan perangkat lunak Anda. tautan: Manfaat
sumber
Saya tidak suka tes tingkat sistem yang ditulis dalam java atau C # karena alasan itu. Lihatlah SpecFlow untuk c # atau salah satu kerangka kerja pengujian berbasis Ketimun untuk java (mungkin JBehave). Maka tes Anda dapat terlihat seperti ini.
Dan Anda dapat mengubah desain objek Anda tanpa harus mengubah semua tes sistem Anda.
(Tes unit "normal" sangat bagus ketika menguji kelas tunggal.)
Apa perbedaan antara kerangka kerja BDD untuk Java?
sumber