Apakah Anda menulis tes unit sepanjang waktu di TDD?

8

Saya telah merancang dan mengembangkan kode dengan gaya TDD untuk waktu yang lama. Yang mengganggu saya tentang TDD adalah menulis tes untuk kode yang tidak mengandung logika bisnis atau perilaku menarik. Saya tahu TDD adalah kegiatan desain lebih dari pengujian tetapi kadang-kadang saya merasa tidak ada gunanya menulis tes dalam skenario ini.

Misalnya saya punya skenario sederhana seperti "Ketika pengguna mengklik tombol centang, itu harus memeriksa validitas file" . Untuk skenario ini saya biasanya mulai menulis tes untuk kelas presenter / controller seperti di bawah ini.

@Test
public void when_user_clicks_check_it_should_check_selected_file_validity(){
    MediaService service =mock(MediaService);
    View view =mock(View);

    when(view.getSelectedFile).thenReturns("c:\\Dir\\file.avi");

    MediaController controller =new MediaController(service,view);
    controller.check();

    verify(service).check("c:\\Dir\\file.avi");
}

Seperti yang Anda lihat, tidak ada keputusan desain atau kode menarik untuk memverifikasi perilaku. Saya menguji nilai dari tampilan yang diteruskan ke MediaService. Saya biasanya menulis tetapi tidak suka tes semacam ini. Apa yang kamu lakukan terhadap situasi ini? Apakah Anda menulis ujian sepanjang waktu?

PEMBARUAN:

Saya telah mengubah nama tes dan kode setelah keluhan. Beberapa pengguna mengatakan bahwa Anda harus menulis tes untuk kasus sepele seperti ini sehingga di masa depan seseorang mungkin menambahkan perilaku yang menarik. Tapi bagaimana dengan "Kode untuk hari ini, desain untuk besok." ? Jika seseorang, termasuk saya, menambahkan kode yang lebih menarik di kemudian hari, tes dapat dibuat untuk itu. Mengapa saya harus melakukannya sekarang untuk kasus-kasus sepele?

caltuntas
sumber
1
"Beberapa pengguna mengatakan bahwa Anda harus menulis tes untuk kasus sepele seperti ini sehingga di masa depan seseorang mungkin menambahkan perilaku yang menarik. Tapi bagaimana dengan" Kode untuk hari ini, desain untuk besok. " ? "Bantahan brilian! +1
maple_shaft

Jawaban:

5

Saya tidak bertujuan untuk 100% dari cakupan kode. Dan saya biasanya tidak menulis tes metode yang jelas tidak akan mengandung logika bisnis dan / atau lebih dari beberapa baris kode. Tapi saya masih menulis unit test (menggunakan TDD) metode yang sepertinya tidak rumit. Ini sebagian besar karena saya ingin memiliki unit test, ketika kembali ke kode itu beberapa bulan atau bahkan bertahun-tahun kemudian, dan ingin membuatnya lebih kompleks. Selalu lebih mudah untuk memperpanjang tes yang ada, daripada harus membangun semuanya dari awal. Seperti kata Noufal, ini subjektif. Saran saya adalah menulis tes, jika Anda berpikir metode ini sedikit rumit atau memiliki potensi untuk menjadi lebih kompleks.


sumber
2

Ini adalah pertanyaan TDD kedua hari ini yang menyampaikan kekesalan pada jumlah tes yang akan ditulis.

"Ujilah hanya jika kamu ingin itu berhasil."

Saya tidak begitu yakin saya memahami tes dalam pertanyaan.

Apakah Anda memeriksa Kontroler itu. Periksa () mendelegasikan ke layanan (ketergantungan) dengan argumen sebagai nilai file yang dipilih dari tampilan? Jika ya, ini adalah ujian yang bagus. Ini memungkinkan Anda untuk menguji controller tanpa implementasi layanan yang sebenarnya. (tes mikro berbasis interaksi).

Pembaruan: Sekarang saya mengerti apa yang Anda coba untuk menguji, saya mungkin akan memindahkan beberapa kode dan mengubah nama beberapa hal sehingga berbunyi "delegasi Test Media Controller memilih file cek ke layanan media." - yang merupakan spesifikasi valid untuk controller.

public class TestMediaController

@Test
public void DelegatesSelectedFileCheckToMediaService(){
    string selectedMediaFileInView = "c:\\Dir\\file.avi";

    when(_view.getSelectedFile).thenReturns(selectedMediaFileInView);

    new MediaController(_service, _view).check();

    verify(_service).check(selectedMediaFileInView);
}
Gishu
sumber
Ya Ini mendelegasikan ke kelas layanan.
Tetapi pertanyaan: apakah layak untuk menulis tes ini hanya untuk memverifikasi parameter yang diteruskan dari tampilan ke kelas layanan?
@Ya - ini menguji apakah centang () terhubung dengan benar. Seharusnya ada tes lain bahwa Service.Check () berfungsi setelah menerima panggilan. Tes ini terlihat sepele hari ini tetapi seiring berjalannya waktu seseorang mungkin menambahkan lebih banyak kode untuk metode ini (misalnya klausa penjaga jika beberapa kondisi kembali;) dan merusak perilaku yang ada. Tes ini penjaga aman terhadap itu.
Gishu
Ok saya mengerti maksud Anda tetapi bagaimana dengan "Kode untuk hari ini, desain untuk besok." ? Jika seseorang atau saya menambahkan kode yang lebih menarik di masa depan saya dapat membuat tes untuk itu. Mengapa saya harus melakukannya sekarang untuk kasus-kasus sepele?
1
@ mcaaltuntas: inti dari TDD adalah Anda menguji spesifikasi saat ini, sehingga jika perubahan kode di masa depan tidak lagi memenuhi spesifikasi saat ini, Anda mengetahuinya. Tidak peduli betapa mudahnya Anda berpikir untuk mengimplementasikan spek sekarang, seseorang mungkin di masa depan mengubah kode tanpa memperhatikan persyaratan khusus ini, dalam hal ini mereka mungkin melanggarnya dan mereka tidak akan menyadari bahwa mereka perlu menambahkan tes untuk itu. . Jika Anda tidak menulis tes sekarang, maka Anda tidak melakukan TDD. Jika Anda tidak ingin menguji keseluruhan spesifikasi, itu adalah panggilan Anda, tetapi Anda tidak menerapkan TDD ke bagian itu.
Steve Jessop
1

Saya tidak akan menulis tes seperti itu (atau setidaknya saya tidak akan menyebutkannya seperti itu). Sebagai gantinya, saya akan menulis tes untuk fitur yang memerlukan panggilan itu check(), sehingga jika pemeriksaan itu atau tindakan yang setara tidak dilakukan, fitur tingkat tinggi tidak akan berfungsi. Mengapa kode Anda perlu memanggil check()metode ini?

Secara umum, saya mencoba untuk menjaga tes dipisahkan dari detail implementasi, sehingga setidaknya nama tes hanya berbicara tentang fitur-fitur eksternal yang disediakan oleh objek. Detail implementasi seperti objek dan metode tidak disebutkan dalam nama tes.

Ini membuatnya lebih mudah untuk melakukan refactoring (tidak perlu perlu mengubah tes ketika Anda mengubah implementasi) dan juga akan membuatnya lebih mudah untuk mengetahui apakah tes sudah usang (fitur yang ditentukan tidak diperlukan lagi) . Ini juga akan membuatnya lebih mudah untuk melihat kode yang tidak perlu / mati, karena boilerplate tingkat rendah (seperti getter dan setter) hanya akan ditambahkan / disimpan jika mereka diharuskan oleh fitur tingkat yang lebih tinggi.

Esko Luontola
sumber
Oke. Anda benar tentang penamaan, Anda bisa memikirkan namanya "ketika pengguna mengklik periksa itu harus memeriksa properti file yang dipilih". Tetapi pertanyaannya bukan tentang penamaan Apakah Anda menulis tes untuk kode "jelas" atau tidak
Saya telah mengubah nama tes tetapi pertanyaan masih ada.
Apa yang harus dilakukan sistem, jika pemeriksaan itu gagal? Melempar pengecualian atau sesuatu yang lain? Saya mungkin akan menulis dua tes: apa yang terjadi ketika file tersebut valid, dan ketika itu tidak valid. Jika ada banyak cara file tidak valid, saya akan menulis tes tersebut langsung terhadap MediaService.
Esko Luontola
Ya Probaby Saya akan menulis dua tes juga tetapi tidak terhadap kelas Controller Saya akan menulis mereka terhadap (seperti yang Anda katakan) kelas MediaService. Jadi Sebenarnya tes hanya memverifikasi kelas layanan telah dipanggil dengan parameter dari tampilan. Apakah menurut Anda layak menulis tes ini hanya untuk memverifikasi argumen yang disampaikan dari tampilan ke kelas layanan?
"Apakah menurut Anda layak menulis tes ini untuk hanya memverifikasi argumen yang disampaikan dari tampilan ke kelas layanan?" Tergantung. Jika ada tes end-to-end di tempat yang memastikan bahwa pemeriksaan berfungsi (yaitu memberikan pesan kesalahan atau sesuatu ketika file tidak valid), maka untuk tes unit pengendali mungkin cukup untuk hanya memeriksa bahwa metode disebut; itu akan memberikan perlindungan lebih cepat selama refactoring daripada tes end-to-end.
Esko Luontola
0

Ini subjektif. Saya tidak selalu melakukan TDD tetapi ketika saya melakukannya, saya mencoba untuk menjaga cakupan kode sebagai metrik saya apakah tes saya komprehensif atau tidak. Kadang-kadang, saya menjadi malas dan hanya melewatkan bagian yang bagi saya tampak "jelas". Kadang-kadang, saya melanggar siklus Red, Green, Refactor dan menulis lebih banyak kode daripada yang diperlukan, tetapi seiring waktu, saya mendapatkan ritme yang membuat saya nyaman.

Noufal Ibrahim
sumber
0

Interaksi antara kelas-kelas seperti di atas dan orisinal yang lebih sederhana saya akan menulis tes untuk. Interaksi dapat menjadi lebih kompleks dari waktu ke waktu sehingga memiliki pekerjaan dasar di tempat adalah hal yang baik.

mlk
sumber
0

Jika seseorang atau saya menambahkan kode yang lebih menarik di masa depan saya dapat membuat tes untuk itu. Mengapa saya harus melakukannya sekarang untuk kasus-kasus sepele?

Anda berasumsi bahwa di masa depan seseorang akan tahu bahwa elemen UI ini ada dan apa yang disebutnya di backend.

Proyek saya saat ini memiliki lebih dari 30 pengembang di enam tim berbeda di dalam basis kode yang sama. Penambahan UI sepele menghilang ke kabut sepanjang waktu. Tidak ada yang akan kembali dan menambahkan test case untuk ini nanti karena tidak ada yang akan mengingat itu ada dan ketika rusak permintaan menjadi "Mengapa mereka tidak menulis tes? Itu akan sangat sederhana!"

Christopher Bibbs
sumber
0

Seperti biasa...

Tergantung

Sulit untuk melihat manfaat dari tes khusus ini dalam konteks TDD karena kita tidak tahu ceritanya.

Jika ceritanya adalah sebagai [pengguna media] saya ingin [dapat memeriksa validitas media] sehingga [saya akan tahu kapan file tidak tersedia]

maka skenario Diberikan [tombol cek media] Ketika [pengguna mengklik tombol] Kemudian [validitas file diperiksa]

masuk akal. Itu sepele, tapi masuk akal.

Jika cerita menyeluruh lebih besar dari ini, maka definisi skenario mungkin terlalu sempit.

Ingat:

TDD! = Pengujian Unit

Fitur tes TDD . Jika ini adalah fitur, maka layak untuk diuji untuk memverifikasinya.

Steven A. Lowe
sumber