Masalah terjadi saat melakukan TDD. Setelah beberapa tes lulus, tipe-tipe pengembalian beberapa kelas / modul berubah. Dalam bahasa pemrograman yang diketik secara statis, jika objek mocked sebelumnya digunakan dalam tes beberapa kelas lain dan tidak dimodifikasi untuk mencerminkan perubahan tipe, maka kesalahan kompilasi akan terjadi.
Namun untuk bahasa dinamis, perubahan tipe pengembalian mungkin tidak terdeteksi dan tes dari kelas lain masih akan berlalu. Tentu mungkin ada tes integrasi yang harus gagal nanti, tetapi unit test akan keliru berlalu. Apakah ada cara bagaimana menghindari ini?
Memperbarui dengan sampel sepele (pada beberapa bahasa yang dibuat-buat) ...
Versi 1:
Calc = {
doMultiply(x, y) {return x * y}
}
//.... more code ....
// On some faraway remote code on a different file
Rect = {
computeArea(l, w) {return Calc.doMultipy(x*y)}
}
// test for Rect
testComputeArea() {
Calc = new Mock()
Calc.expect(doMultiply, 2, 30) // where 2 is the arity
assertEqual(30, computeArea)
}
Sekarang, pada versi 2:
// I change the return types. I also update the tests for Calc
Calc = {
doMultiply(x, y) {return {result: (x * y), success:true}}
}
... Rect akan melempar eksepsi pada runtime, namun tes masih akan berhasil.
sumber
class X
, tetapi tesclass Y
yang bergantung padaX
dan dengan demikian diuji terhadap kontrak yang berbeda dari apa yang bertentangan dalam produksi.Jawaban:
Sampai batas tertentu, ini hanya sebagian dari biaya berbisnis dengan bahasa yang dinamis. Anda mendapatkan banyak fleksibilitas, atau dikenal sebagai "tali cukup untuk menggantung diri sendiri". Hati-hati dengan itu.
Bagi saya, masalahnya menyarankan menggunakan teknik refactoring yang berbeda dari yang Anda lakukan dalam bahasa yang diketik secara statis. Dalam bahasa statis, Anda mengganti tipe pengembalian sebagian sehingga Anda dapat "bersandar pada kompiler" untuk menemukan tempat yang mungkin rusak. Ini aman untuk dilakukan, dan mungkin lebih aman daripada memodifikasi tipe pengembalian di tempat.
Dalam bahasa yang dinamis, Anda tidak bisa melakukan itu, jadi jauh lebih aman untuk memodifikasi tipe pengembalian di tempat, daripada menggantinya. Mungkin, Anda memodifikasinya dengan menambahkan kelas baru Anda sebagai anggota, untuk kelas yang membutuhkannya.
sumber
Jika kode Anda berubah dan tes Anda masih lulus, maka ada sesuatu yang salah dengan tes Anda (yaitu Anda kehilangan penegasan), atau kode itu tidak benar - benar berubah.
Apa yang saya maksud dengan itu? Nah, tes Anda menjelaskan kontrak antara bagian-bagian kode Anda. Jika kontrak adalah "nilai kembali harus dapat diubah", maka mengubah nilai kembali dari mengatakan array ke daftar sebenarnya bukan perubahan dalam kontrak, dan karena itu tidak akan serta merta memicu kegagalan pengujian.
Untuk menghindari pernyataan yang hilang, Anda dapat menggunakan alat-alat seperti analisis cakupan kode (tidak akan memberi tahu Anda bagian mana dari kode Anda yang diuji, tetapi akan memberi tahu Anda bagian mana yang tidak diuji), kompleksitas siklus dan kompleksitas NPath (yang memberi Anda batas bawah pada jumlah pernyataan yang diperlukan untuk mencapai cakupan kode C1 dan C2 penuh) dan penguji mutasi (yang menyuntikkan mutasi dalam kode Anda seperti beralih
true
kefalse
, angka negatif menjadi positif, objek menjadinull
dll, dan memeriksa apakah itu membuat tes gagal).sumber