Tes ada untuk mendukung dan memastikan pemrograman defensif
Pemrograman defensif melindungi integritas sistem saat runtime.
Tes adalah alat diagnostik (kebanyakan statis). Saat runtime, tes Anda tidak terlihat. Mereka seperti perancah yang digunakan untuk memasang tembok bata tinggi atau kubah batu. Anda tidak meninggalkan bagian penting dari struktur karena Anda memiliki perancah yang menahannya selama konstruksi. Anda memiliki perancah yang menahannya selama konstruksi untuk memudahkan memasukkan semua bagian penting.
EDIT: Sebuah analogi
Bagaimana dengan analogi komentar dalam kode?
Komentar memiliki tujuan, tetapi bisa berlebihan atau bahkan berbahaya. Misalnya, jika Anda memasukkan pengetahuan intrinsik tentang kode ke dalam komentar , lalu ubah kodenya, komentar menjadi tidak relevan yang terbaik dan berbahaya paling buruk.
Jadi katakan Anda memasukkan banyak pengetahuan intrinsik dari basis kode Anda ke dalam tes, seperti MethodA tidak dapat mengambil nol dan argumen MethodB harus > 0
. Kemudian kodenya berubah. Null oke untuk A sekarang, dan B dapat mengambil nilai sekecil -10. Tes yang ada sekarang salah secara fungsional, tetapi akan terus berlalu.
Ya, Anda harus memperbarui tes pada saat yang sama Anda memperbarui kode. Anda juga harus memperbarui (atau menghapus) komentar pada saat yang sama saat Anda memperbarui kode. Tetapi kita semua tahu hal-hal ini tidak selalu terjadi, dan bahwa kesalahan telah terjadi.
Tes memverifikasi perilaku sistem. Perilaku aktual itu intrinsik ke sistem itu sendiri, bukan intrinsik pada tes.
Apa yang mungkin salah?
Tujuan yang berkaitan dengan tes adalah untuk memikirkan segala sesuatu yang bisa salah, menulis tes untuk itu yang memeriksa perilaku yang benar, kemudian menyusun kode runtime sehingga melewati semua tes.
Yang berarti pemrograman defensif adalah intinya .
TDD menggerakkan pemrograman defensif, jika tesnya komprehensif.
Lebih banyak tes, mendorong pemrograman yang lebih defensif
Ketika bug ditemukan, lebih banyak tes ditulis untuk memodelkan kondisi yang memanifestasikan bug. Kemudian kode diperbaiki, dengan kode untuk membuat tes - tes itu berlalu, dan tes-tes baru tetap di dalam test suite.
Seperangkat tes yang baik akan melewati argumen baik dan buruk ke fungsi / metode, dan mengharapkan hasil yang konsisten. Ini, pada gilirannya, berarti komponen yang diuji akan menggunakan pemeriksaan prakondisi (pemrograman defensif) untuk mengkonfirmasi argumen yang diberikan kepadanya.
Secara umum ...
Misalnya, jika argumen nol untuk prosedur tertentu tidak valid, maka setidaknya satu tes akan lulus nol, dan itu akan mengharapkan pengecualian / kesalahan "argumen nol tidak valid" dari beberapa jenis.
Setidaknya satu tes lain akan melewati argumen yang valid , tentu saja - atau loop melalui array besar dan melewati beberapa argumen yang valid - dan mengkonfirmasi bahwa keadaan yang dihasilkan sesuai.
Jika tes tidak lulus argumen nol itu dan ditampar dengan pengecualian yang diharapkan (dan pengecualian itu dilemparkan karena kode memeriksa keadaan yang diteruskan secara defensif), maka nol dapat berakhir ditugaskan ke properti kelas atau dikubur dalam koleksi semacam di mana seharusnya tidak.
Ini mungkin menyebabkan perilaku tak terduga di beberapa bagian sistem yang sama sekali berbeda tempat instance kelas diteruskan, di beberapa lokasi geografis yang jauh setelah perangkat lunak dikirimkan . Dan itu adalah hal yang sebenarnya kita coba hindari, kan?
Itu bahkan bisa lebih buruk. Instance class dengan state yang tidak valid dapat diserialisasi dan disimpan, hanya untuk menyebabkan kegagalan ketika itu disusun kembali untuk digunakan nanti. Ya ampun, saya tidak tahu, mungkin ini semacam sistem kontrol mekanis yang tidak dapat memulai kembali setelah dimatikan karena tidak dapat menghapus status konfigurasi persistennya sendiri. Atau instance kelas dapat serial dan diteruskan ke beberapa sistem yang sama sekali berbeda yang dibuat oleh beberapa entitas lain, dan bahwa sistem mungkin crash.
Terutama jika pemrogram sistem lain itu tidak kode pertahanan.