Awalnya TDD berasal dari gerakan lincah, di mana pengujian ditulis di muka sebagai cara untuk memastikan apa yang Anda kodekan tetap benar mengingat spesifikasi yang sekarang didefinisikan dengan baik dalam kode pengujian. Itu juga muncul sebagai aspek yang sangat penting dari refactoring, ketika Anda memodifikasi kode Anda, Anda bisa mengandalkan tes untuk membuktikan bahwa Anda tidak mengubah perilaku kode.
Kemudian alat orang datang dan berpikir mereka tahu informasi tentang kode Anda dan kemudian dapat menghasilkan potongan uji untuk membantu Anda dalam menulis tes unit Anda, dan saya pikir ini adalah di mana semuanya salah.
Rintisan pengujian dihasilkan oleh komputer yang tidak memiliki petunjuk apa yang Anda lakukan, hanya menghasilkan sebuah rintisan tanpa berpikir untuk setiap metode karena itulah yang diperintahkan untuk dilakukan. Ini berarti Anda memiliki test case untuk setiap metode terlepas dari kompleksitas metode itu atau apakah cocok untuk pengujian secara terpisah.
Ini datang pada pengujian dari ujung metodologi TDD yang salah. Di TDD Anda harus mencari tahu apa kode yang harus dilakukan, dan kemudian menghasilkan kode yang mencapai ini. Ini memuaskan karena Anda akhirnya menulis tes yang membuktikan bahwa kode melakukan apa yang dilakukan kode, bukan apa yang seharusnya dilakukan. Dikombinasikan dengan penghentian bertopik pengujian berbasis metode secara otomatis, Anda membuang banyak waktu untuk membuktikan setiap aspek kecil dari kode Anda yang dengan mudah dapat terbukti salah ketika semua bagian kecil disatukan.
Ketika Fowler menggambarkan pengujian dalam bukunya, ia menyebut pengujian setiap kelas dengan metode utamanya sendiri. Dia meningkatkan ini, tetapi konsepnya masih sama - Anda menguji seluruh kelas sehingga bekerja secara keseluruhan, semua tes Anda digabungkan untuk membuktikan interaksi semua metode tersebut sehingga kelas dapat digunakan kembali dengan harapan yang ditentukan.
Saya pikir toolkit uji telah membuat kita merugikan, membawa kita ke jalan berpikir bahwa toolkit adalah satu-satunya cara untuk melakukan hal-hal ketika benar-benar, Anda perlu berpikir lebih banyak untuk diri sendiri untuk mendapatkan hasil terbaik dari kode Anda. Menempatkan kode tes dalam potongan tes kecil untuk potongan kecil hanya berarti Anda harus mengulangi pekerjaan Anda dalam tes integrasi (dan jika Anda akan melakukannya, mengapa tidak melewati tahap uji unit yang sekarang berlebihan sepenuhnya). Ini juga berarti orang membuang banyak waktu untuk mencoba mendapatkan cakupan tes 100%, dan banyak waktu membuat sejumlah besar kode ejekan dan data yang lebih baik dihabiskan untuk membuat kode lebih mudah untuk tes integrasi (yaitu jika Anda memiliki banyak dependensi data, unit test mungkin bukan pilihan terbaik)
Terakhir, kerapuhan unit test berbasis metode hanya menunjukkan masalahnya. Refactoring dirancang untuk digunakan dengan unit test, jika tes Anda rusak sepanjang waktu karena Anda refactoring maka ada yang tidak beres dengan seluruh pendekatan. Refactoring suka membuat dan menghapus metode, jadi jelas pendekatan tes buta per-metode bukanlah yang semula dimaksudkan.
Saya tidak ragu bahwa banyak metode akan mendapatkan tes tertulis untuk mereka, semua metode publik kelas harus diuji, tetapi Anda tidak dapat melepaskan diri dari konsep pengujian bersama sebagai bagian dari satu test case. Sebagai contoh, jika saya memiliki satu set dan metode get, saya dapat menulis tes yang memasukkan data dan memeriksa anggota internal diatur ok, atau saya dapat menggunakan masing-masing untuk memasukkan beberapa data dan kemudian mengeluarkannya lagi untuk melihat apakah itu masih sama dan tidak kacau. Ini menguji kelas, bukan masing-masing metode secara terpisah. Jika setter bergantung pada metode privat pembantu, maka itu tidak masalah - Anda tidak perlu mengejek metode pribadi untuk memastikan setter bekerja, tidak jika Anda menguji seluruh kelas.
Saya pikir agama masuk ke topik ini, maka Anda melihat perpecahan dalam apa yang sekarang dikenal sebagai pengembangan 'didorong oleh perilaku' dan 'didorong oleh ujian' - konsep asli pengujian unit adalah untuk pengembangan yang didorong oleh perilaku.
Seperti namanya Anda menguji subjek atom dalam setiap tes. Subjek seperti itu biasanya merupakan metode tunggal. Beberapa pengujian dapat menguji metode yang sama, untuk menutupi jalan bahagia, kemungkinan kesalahan, dll. Anda menguji perilaku, bukan mekanisme internal. Jadi pengujian unit benar-benar tentang pengujian antarmuka publik kelas, yaitu metode tertentu.
Dalam pengujian unit, suatu metode perlu diuji secara terpisah, yaitu dengan mematikan / mengejek / memalsukan setiap dependensi. Kalau tidak, pengujian unit dengan dependensi 'nyata' menjadikannya sebagai tes integrasi. Ada waktu dan tempat untuk kedua jenis tes. Tes unit memastikan subjek tunggal berfungsi seperti yang diharapkan, mandiri. Tes integrasi memastikan bahwa subjek 'nyata' bekerja bersama dengan benar.
sumber
Aturan praktis saya: Unit terkecil dari kode yang masih cukup kompleks untuk mengandung bug.
Apakah ini metode atau kelas atau subsistem tergantung pada kode tertentu, tidak ada aturan umum yang dapat diberikan.
Misalnya, tidak memberikan nilai apa pun untuk menguji metode pengambil / penyetel sederhana secara terpisah, atau metode pembungkus yang hanya memanggil metode lain. Bahkan seluruh kelas mungkin terlalu sederhana untuk diuji, jika kelas tersebut hanya bungkus tipis atau adaptor. Jika satu-satunya hal yang diuji adalah jika metode pada mock dipanggil, maka kode yang diuji adalah thin.
Dalam kasus lain metode tunggal mungkin melakukan beberapa perhitungan kompleks yang berharga untuk diuji secara terpisah.
Dalam banyak kasus, bagian-bagian kompleks bukanlah kelas individu melainkan integrasi antar kelas. Jadi, Anda menguji dua atau lebih kelas sekaligus. Beberapa orang akan mengatakan bahwa ini bukan tes unit tetapi tes integrasi, tetapi tidak peduli terminologinya: Anda harus menguji di mana kompleksitasnya, dan tes ini harus menjadi bagian dari rangkaian uji.
sumber