Dalam TDD saya harus menulis Test terlebih dahulu atau Interface dulu?

23

Saya belajar TDD menggunakan c #, sejauh yang saya tahu tes harus mendorong pengembangan , yaitu pertama - tama menulis tes gagal setelah menulis kode minimum untuk lulus tes kemudian melakukan refactoring.

Tetapi dikatakan juga bahwa " Program ke Antarmuka, bukan Implementasi ", jadi tulislah antarmuka terlebih dahulu . Di sinilah kebingungan saya dimulai, Jika saya menulis Antarmuka terlebih dahulu maka itu melanggar dua hal

  1. Kode yang ditulis untuk antarmuka tidak didorong oleh tes .

  2. Ini bukan minimum yang jelas saya bisa menulisnya dengan kelas sederhana.

Haruskah saya mulai dengan menulis tes untuk antarmuka juga? tanpa implementasi apa yang akan saya uji?

Jika pertanyaan ini terdengar konyol, maaf, tapi saya benar-benar bingung. Mungkin saya mengambil hal-hal yang terlalu harfiah.

k4vin
sumber
8
"Program ke sebuah antarmuka" berarti memisahkan apa yang Anda butuhkan dari sepotong kode dari bagaimana itu dilakukan. Itu tidak berarti secara harfiah menggunakan interfaceuntuk segalanya. A classjuga menyediakan antarmuka, karena Anda dapat menyembunyikan detail implementasi dalam privatevariabel.
Doval
@Doval, Ya, Anda tidak perlu antarmuka untuk semuanya, hanya apa yang disebut a contract. Ini bisa dalam bentuk kelas abstrak, misalnya, meskipun seharusnya tidak menjadi kelas virtual / metode karena Anda seharusnya tidak dapat membuat instance itu.
trysis
2
TDD berkata, "tulis tes yang gagal." Beberapa TDDers yang ketat mengatakan bahwa itu dianggap sebagai "gagal" jika Anda tidak dapat mengkompilasi tes karena tipe data yang dioperasikan belum dideklarasikan.
Solomon Slow

Jawaban:

29

Pelanggaran pertama Anda ("Kode yang ditulis untuk antarmuka tidak didorong oleh tes.") Tidak valid. Mari kita gunakan contoh sepele. Misalkan Anda sedang menulis kelas kalkulator, dan Anda sedang menulis operasi tambahan. Tes apa yang mungkin Anda tulis?

public class CalculatorTest {
    @Test
    public void testAddTwoIntegers() {
        Calculator calc = new Calculator();
        int result = calc.add(2, 2)
        Assert.assertEquals(4, result);
    }
}

Tes Anda baru saja mendefinisikan antarmuka. Ini addmetodenya, lihat? addmengambil dua argumen dan mengembalikan jumlah mereka. Anda nanti dapat menentukan bahwa Anda memerlukan beberapa Kalkulator, dan mengekstrak antarmuka Java (dalam hal ini) pada waktu itu. Tes Anda seharusnya tidak berubah, karena Anda menguji antarmuka publik dari kelas itu.

Pada tingkat yang lebih teoretis, pengujian adalah spesifikasi yang dapat dieksekusi untuk suatu sistem. Antarmuka ke sistem harus didorong oleh pengguna sistem itu, dan tes adalah metode pertama yang harus Anda tetapkan interaksi.

Saya tidak berpikir Anda dapat memisahkan desain antarmuka dari desain tes. Menentukan interaksi dan merancang tes untuk mereka adalah operasi mental yang sama - ketika saya mengirim informasi ini ke antarmuka, saya mengharapkan hasil tertentu. Ketika ada sesuatu yang salah dengan input saya, saya mengharapkan kesalahan ini. Anda dapat melakukan pekerjaan desain ini di atas kertas dan kemudian menulis tes Anda dari itu, atau Anda dapat melakukannya pada saat yang sama - tidak masalah.

Michael K.
sumber
2
+1 " Saya tidak berpikir Anda dapat memisahkan desain antarmuka dari desain tes " harus dicetak tebal, IMHO :)
Binary Worrier
Bahkan lebih mudah untuk ditampilkan, jika Anda ingin menguji lebih dari satu implementasi fungsi, kata Impor XML dan Impor CSV, Anda dapat mengujinya dengan metode yang persis sama dari antarmuka yang sama meskipun implementasinya akan berubah. Selain itu, tes sering melibatkan beberapa ejekan, dan untuk antarmuka ini diperlukan.
Walfrat
Anda mengatakan tes tidak perlu diubah, tetapi new Calculator()apakah implementasinya benar? Jika ada implementasi baru yang diperlukan, mungkin Anda akan melakukan MultiplicationCalculator, dan Anda perlu mengubah tes untuk menggunakannya new AdditionCalculator()agar tetap lulus? Atau apakah saya melewatkan sesuatu?
Steve Chamaillard
3
@SteveChamaillard Tentu, jika desain Anda mengharuskan Anda mengubah nama kelas dari Kalkulator ke AdditionCalculator, tes harus diubah agar sesuai. Tentu saja, dengan melakukan TDD apa yang sebenarnya akan terjadi adalah Anda akan mengubah tes terlebih dahulu, dan perubahan kelas akan mengikuti untuk membuat lulus ujian.
Eric King
5

Apa yang kita lakukan saat menulis interface? Apakah kita menulis kode, atau sedang merancang?

Saya bukan penggemar gagasan Test Driven Design, tapi saya suka Test Driven Development . Secara pribadi, saya mendapatkan hasil terbaik ketika merancang kelas di muka dengan mendesain antarmuka sebelum menulis tes. Saya tidak menghitung antarmuka sebagai kode. Antarmuka adalah desain yang akan saya implementasikan menggunakan TDD. Ini sepertinya akan mengubah sebuah evolusi saat saya bekerja, tetapi ini adalah peta jalan saya (bersama dengan daftar tes saya).

Saya akan berhenti sebelum saya mulai berteriak-teriak, tetapi mudah-mudahan itu cara yang bermanfaat bagi Anda untuk memikirkannya.

Bebek karet
sumber
4

Dalam TDD saya harus menulis Test terlebih dahulu atau Interface dulu?

Itu semua tergantung pada seberapa ortodoks / religius Anda ingin melakukan TDD .

Saya sedang belajar TDD

Karena Anda sedang belajar, Anda harus bereksperimen untuk mendapatkan alur kerja pribadi, yang cocok untuk Anda.

  1. Jika Anda ingin melakukannya sesuai dengan buku , Anda menulis pada awalnya tes, yang jelas akan gagal, karena Anda mulai tanpa kode sama sekali. Kemudian Anda menulis beberapa kode untuk lulus ujian. Jika itu dilakukan, Anda bebas untuk refactor kode yang ada, karena Anda memiliki tes yang menyediakan semacam jaring pengaman untuk refactor. Memutuskan untuk menggunakan Antarmuka adalah semacam refactoring.

  2. Selain TDD atau tidak: Pertanyaannya, apakah menggunakan antarmuka atau tidak tidak menarik pada awalnya. Tentu saja jika Anda yakin, Anda memiliki perilaku berbeda yang ingin Anda sebarkan ke beberapa objek, masuk akal untuk berpikir tentang menggunakan Antarmuka: Misalnya, jika Anda memiliki semacam output ke tujuan yang berbeda, masuk akal untuk mengimplementasikannya melalui Writer antarmuka dan memiliki kelas yang berbeda untuk output ( FileWriter , Printer dll.) Meskipun itu adalah pepatah umum untuk menulis ke sebuah antarmuka , tetapi itu tidak berarti: gunakan antarmuka untuk semuanya . Terkadang itu satu tingkat tipuan untuk banyak. Btw. hal yang sama berlaku untuk layanan. Tapi itu topik yang berbeda.

  3. Di sisi lain, Anda dapat mengembangkan tes didorong dengan cara lain: rancang kode Anda untuk testabilitas. Yang berarti, Anda menulis kode, yang mudah untuk diuji - meskipun Anda menulis tes sesudahnya . Tidak masalah jika Anda menulis tes sebelumnya atau sesudahnya, selama Anda melakukan tes.

Thomas Junk
sumber
5
Tidak dapat setuju dengan poin terakhir "Tidak masalah jika Anda menulis tes sebelumnya atau sesudahnya, selama Anda menguji anyways". Jika Anda menulis tes sesudahnya, Anda tidak dapat memastikan apakah tes ini menguji hal yang benar.
k4vin
4
Seperti yang saya katakan ... Itu tergantung pada seberapa ortodoks Anda ...
Thomas Junk
2

TDD atau BDD berarti Melakukan antarmuka domain Anda terlebih dahulu dan kemudian menulis tes terhadap mereka dengan interpretasi saya. implementasi antarmuka memiliki perilaku yang diharapkan.

itu masih menguji sebelum kode karena suatu antarmuka tidak mengandung logika yang dapat diuji itu adalah struktur yang Anda tulis untuk diuji.

Saya Akan Melakukannya sebagai berikut

  1. Tulis Perilaku Semi Formal (Diberikan: Kapan: Lalu :)

  2. Tulis Antarmuka (untuk meng-host metode pengkodean perilaku)

  3. Tulis Tes yang Diidentifikasi (masukan yang diberikan, panggil kapan, uji kemudian)

  4. Tulis / Ubah Beton (Kelas yang mengimplementasikan antarmuka) untuk Lulus Tes

pengguna3721330
sumber
0

Jangan pernah menulis tes sebelum Anda mendesain antarmuka. Ketika Anda berpikir tentang jenis tes apa yang harus ditulis (desain tes) Anda tidak harus secara bersamaan merancang (merancang) aplikasi Anda. Jangan memikirkan dua hal sekaligus. Pernahkah Anda mendengar tentang pemisahan kekhawatiran? Ini berlaku tidak hanya untuk struktur fisik kode Anda tetapi juga untuk proses berpikir Anda.

Putuskan bagaimana aplikasi Anda harus dirancang terlebih dahulu. Ini berarti Anda mendesain antarmuka dan hubungan antar antarmuka ini. Sampai Anda selesai melakukan ini, Anda sebaiknya tidak mulai memikirkan tes. Setelah Anda tahu apa antarmuka Anda maka Anda dapat terlebih dahulu membuat mereka dan kemudian menulis tes terhadap mereka atau menulis tes pertama dan kemudian membuatnya. Dalam kasus terakhir jelas Anda tidak akan dapat mengkompilasi tes. Saya tidak melihat ada salahnya atau pelanggaran filosofi TDD dalam menciptakan antarmuka sebelum tes.

Nissim Levy
sumber
alasan dalam jawaban teratas terlihat lebih menarik: "Saya tidak berpikir Anda dapat memisahkan desain antarmuka dari desain tes. Mendefinisikan interaksi dan merancang tes untuk mereka adalah operasi mental yang sama - ketika saya mengirim informasi ini ke dalam antarmuka, saya mengharapkan hasil tertentu . Ketika sesuatu yang salah dengan masukan saya, saya berharap kesalahan ini ..."
nyamuk
@gnat Saya percaya Nissam di sini mengacu pada interfacekata kunci C # , bukan istilah umum "antarmuka".
RubberDuck
@ RubberDuck Saya juga berpikir begitu dan saya percaya ini adalah pendekatan yang buruk. "Sampai Anda selesai melakukan ini, Anda tidak boleh mulai memikirkan tes ..." Seperti yang saya tulis, alasan dalam jawaban teratas terlihat lebih menarik, baik dalam arti antarmuka umum maupun dalam arti kata kunci konkret
nyamuk
@Gnat cukup adil yang tidak jelas dari komentar Anda. Secara pribadi, saya setuju dengan Nissam di sini. Saya menemukan ini menghentikan orang untuk menggunakan TDD sebagai alasan untuk tidak merancang sama sekali. YMMV.
RubberDuck
-2

Tidak apa-apa untuk menulis antarmuka / kode / tes pada saat yang sama selama penggabungan mereka ke dalam proyek adalah atom.

Kecuali jika bos Anda religius dengan TDD, dalam hal ini Anda mungkin harus menulis antarmuka kosong -> tes -> kode minimal (langkah tanpa titik) -> lebih banyak tes -> lebih banyak kode tanpa titik -> lebih banyak tes -> akhirnya tulis kode sebenarnya - > selesai.

alternatif
sumber