Saya mengikuti TDD dengan religius. Proyek saya biasanya memiliki cakupan pengujian 85% atau lebih baik, dengan kasus uji yang bermakna.
Saya melakukan banyak pekerjaan dengan HBase , dan antarmuka klien utama, HTable, sangat menyebalkan. Diperlukan 3 atau 4 kali lebih lama untuk menulis tes unit saya daripada menulis tes yang menggunakan titik akhir langsung.
Saya tahu bahwa, secara filosofis, tes yang menggunakan ejekan harus lebih diprioritaskan daripada tes yang menggunakan titik akhir langsung. Tapi mengejek HTable adalah rasa sakit yang serius, dan saya tidak begitu yakin ini menawarkan banyak keuntungan dibandingkan pengujian terhadap contoh HBase langsung.
Semua orang di tim saya menjalankan instance HBase node tunggal di workstation mereka, dan kami memiliki instance HBase node tunggal yang berjalan di kotak Jenkins kami, jadi ini bukan masalah ketersediaan. Tes titik akhir langsung jelas membutuhkan waktu lebih lama untuk dijalankan daripada tes yang menggunakan ejekan, tetapi kami tidak terlalu peduli soal itu.
Saat ini, saya menulis tes titik akhir langsung DAN tes berbasis mock untuk semua kelas saya. Saya ingin membuang tiruannya, tetapi saya tidak ingin kualitasnya menurun.
Apa yang kalian pikirkan?
sumber
Jawaban:
Rekomendasi pertama saya adalah untuk tidak mengejek tipe yang tidak Anda miliki . Anda menyebut HTable sangat menyebalkan - mungkin Anda harus membungkusnya di Adaptor yang memperlihatkan 20% fitur HTable yang Anda butuhkan, dan mengejek pembungkus jika diperlukan.
Yang sedang berkata, mari kita asumsikan kita berbicara tentang tipe Anda semua miliki. Jika pengujian berbasis tiruan Anda berfokus pada skenario jalur bahagia di mana semuanya berjalan lancar, Anda tidak akan kehilangan apa pun karena mereka gagal. Tes integrasi Anda mungkin sudah menguji jalur yang sama persis.
Namun, tes terisolasi menjadi menarik ketika Anda mulai berpikir tentang bagaimana sistem Anda sedang diuji harus bereaksi terhadap setiap hal kecil yang dapat terjadi seperti yang didefinisikan dalam kontrak kolaboratornya, terlepas dari objek konkret yang sebenarnya diajak bicara. Itulah bagian dari apa yang disebut beberapa kebenaran mendasar . Mungkin ada banyak kasus kecil dan banyak kombinasi lainnya. Di sinilah tes integrasi mulai menjadi buruk sementara tes terisolasi akan tetap cepat dan dikelola.
Agar lebih konkret, apa yang terjadi jika salah satu metode adaptor HTable Anda mengembalikan daftar kosong? Bagaimana jika mengembalikan nol? Bagaimana jika itu melempar pengecualian koneksi? Ini harus didefinisikan dalam kontrak Adaptor jika hal-hal itu dapat terjadi, dan konsumen mana pun harus siap untuk menghadapi situasi ini , maka diperlukan pengujian untuk mereka.
Singkatnya: Anda tidak akan melihat penurunan kualitas dengan menghapus tes berbasis tiruan Anda jika mereka menguji hal-hal yang sama persis seperti tes integrasi Anda . Namun, mencoba membayangkan tes terisolasi tambahan (dan tes kontrak ) dapat membantu Anda memikirkan antarmuka / kontrak Anda secara luas dan meningkatkan kualitas dengan mengatasi cacat yang sulit dipikirkan dan / atau lambat untuk diuji dengan tes integrasi.
sumber
Saya pikir setidaknya, itulah titik kontroversi yang sedang berlangsung saat ini di antara para pendukung TDD.
Pandangan pribadi saya lebih dari itu untuk mengatakan bahwa tes berbasis mock sebagian besar merupakan cara untuk mewakili bentuk kontrak antarmuka ; idealnya rusak (yaitu gagal) jika dan hanya jika Anda mengubah antarmuka . Dan dengan demikian, dalam bahasa yang diketik dengan cukup kuat seperti Java, dan ketika menggunakan antarmuka yang didefinisikan secara eksplisit, itu hampir seluruhnya berlebihan: kompiler akan memberi tahu Anda jika Anda telah mengubah antarmuka.
Pengecualian utama adalah ketika Anda menggunakan antarmuka yang sangat umum, mungkin berdasarkan pada anotasi atau refleksi, bahwa kompiler tidak dapat berguna secara otomatis menjadi polisi. Bahkan kemudian Anda harus memeriksa untuk melihat apakah ada cara melakukan validasi secara terprogram (misalnya perpustakaan memeriksa sintaks SQL) daripada dengan tangan menggunakan mengejek.
Ini adalah kasus terakhir yang Anda lakukan ketika Anda menguji dengan database lokal 'hidup'; implementasi htable dimulai dan menerapkan validasi kontrak interfacve yang jauh lebih komprehensif daripada yang pernah Anda pikirkan untuk ditulis dengan tangan.
Sayangnya, penggunaan pengujian berbasis mock yang jauh lebih umum adalah pengujian yang:
Tentu saja tes semacam itu harus dihapus saat dilihat.
sumber
Berapa lama tes berbasis endpoint dapat dijalankan daripada tes berbasis mock? Jika ini jauh lebih lama, maka ya, layak investasi waktu penulisan tes Anda untuk membuat tes unit lebih cepat - karena Anda harus menjalankannya berkali-kali. Jika tidak signifikan lebih lama, meskipun tes berbasis titik akhir bukan tes unit "murni", selama mereka melakukan pekerjaan yang baik untuk menguji unit, tidak ada alasan untuk bersikap religius tentang hal itu.
sumber
Saya setuju sepenuhnya dengan respons guillaume31, tidak pernah mengejek tipe yang tidak Anda miliki !.
Biasanya rasa sakit dalam pengujian (mengejek antarmuka yang kompleks) mencerminkan masalah dalam desain Anda. Mungkin Anda memerlukan beberapa abstraksi antara model Anda dan kode akses data Anda, contoh formulir menggunakan arsitektur heksagonal dan pola repositori, cara paling umum untuk menyelesaikan masalah semacam ini.
Jika Anda ingin melakukan tes integrasi untuk memeriksa hal-hal melakukan tes integrasi, jika Anda ingin melakukan tes unit karena Anda menguji logika Anda melakukan tes unit dan mengisolasi dari kegigihan. Tetapi melakukan tes integrasi karena Anda tidak tahu bagaimana mengisolasi logika Anda dari sistem eksternal (atau karena mengisolasi rasa sakitnya) itu bau yang besar, Anda memilih integrasi daripada unit untuk batasan dalam desain Anda bukan untuk kebutuhan nyata. untuk menguji integrasi.
Lihatlah formulir pembicaraan ini Ian cooper: http://vimeo.com/68375232 , ia berbicara tentang arsitektur dan pengujian heksagonal, ia berbicara tentang kapan dan apa yang harus diejek, pembicaraan yang benar-benar terinspirasi yang memecahkan banyak pertanyaan seperti pertanyaan Anda tentang TDD nyata .
sumber
TL; DR - Cara saya melihatnya, itu tergantung pada seberapa banyak usaha yang Anda habiskan untuk tes, dan apakah lebih baik menghabiskan lebih banyak pada sistem Anda yang sebenarnya.
Versi panjang:
Beberapa jawaban bagus di sini, tetapi pendapat saya berbeda: pengujian adalah kegiatan ekonomi yang perlu membayar kembali untuk dirinya sendiri, dan jika waktu yang Anda habiskan tidak dikembalikan dalam pengembangan dan keandalan sistem (atau apa pun yang Anda cari untuk keluar tes) maka Anda mungkin melakukan investasi yang buruk; Anda berada dalam bisnis membangun sistem, bukan menulis tes. Oleh karena itu, mengurangi upaya untuk menulis dan mempertahankan tes sangat penting.
Misalnya, beberapa nilai utama yang saya peroleh dari tes adalah:
Pengujian terhadap titik akhir langsung masih harus menyediakan ini.
Beberapa kelemahan untuk pengujian terhadap titik akhir langsung:
Jika saya berada dalam situasi ini, dan kekurangannya tampaknya tidak menjadi masalah sedangkan mengejek titik akhir memperlambat penulisan tes saya, saya akan menguji terhadap titik akhir langsung dalam detak jantung, selama saya akan yakin untuk periksa lagi setelah beberapa saat untuk melihat bahwa kekurangannya ternyata tidak menjadi masalah dalam praktik.
sumber
Dari perspektif pengujian ada beberapa persyaratan yang mutlak harus:
Itu tantangan besar ketika menghubungkan ke sumber mana pun yang mempertahankan keadaan di luar tes Anda. Ini bukan TDD "murni", tetapi kru Ruby on Rails menyelesaikan masalah ini dengan cara yang mungkin dapat diadaptasi untuk tujuan Anda. Kerangka uji rel bekerja dengan cara ini:
Semua pekerjaan ini dibangun ke dalam test harness, dan bekerja dengan cukup baik. Ada banyak lagi, tetapi dasar-dasarnya sudah cukup untuk percakapan ini.
Pada tim berbeda yang telah bekerja sama dengan saya dari waktu ke waktu, kami akan membuat pilihan yang akan mempromosikan kode diuji meskipun itu bukan jalan yang paling benar. Idealnya, kami akan membungkus semua panggilan ke penyimpanan data dengan kode yang kami kontrol. Secara teori, jika salah satu dari proyek-proyek lama ini mendapatkan dana baru, kita dapat kembali dan memindahkannya dari basis data yang terikat ke Hadoop dengan memfokuskan perhatian kita hanya pada beberapa kelas saja.
Aspek penting adalah tidak mengacaukan data produksi, dan pastikan Anda benar-benar menguji apa yang Anda pikir Anda uji. Sangat penting untuk dapat mereset layanan eksternal ke baseline yang diketahui berdasarkan permintaan - bahkan dari kode Anda.
sumber