Saya sering bekerja dengan program yang sangat numerik / matematis, di mana hasil pasti dari suatu fungsi sulit diprediksi sebelumnya.
Dalam mencoba menerapkan TDD dengan kode semacam ini, saya sering menemukan bahwa menulis kode yang sedang diuji secara signifikan lebih mudah daripada menulis unit test untuk kode itu, karena satu-satunya cara saya tahu untuk menemukan hasil yang diharapkan adalah menerapkan algoritma itu sendiri (baik dalam kepala, di atas kertas, atau oleh komputer). Ini terasa salah, karena saya secara efektif menggunakan kode yang sedang diuji untuk memverifikasi unit test saya, bukan sebaliknya.
Adakah teknik yang dikenal untuk menulis unit test dan menerapkan TDD ketika hasil kode yang diuji sulit diprediksi?
Contoh kode (nyata) dengan hasil yang sulit diprediksi:
Sebuah fungsi weightedTasksOnTime
yang, diberikan sejumlah pekerjaan yang dilakukan per hari workPerDay
dalam kisaran (0, 24], waktu saat ini initialTime
> 0, dan daftar tugas taskArray
; masing-masing dengan waktu untuk menyelesaikan properti time
> 0, tanggal jatuh tempo due
, dan nilai penting importance
; pengembalian nilai yang dinormalisasi dalam rentang [0, 1] mewakili pentingnya tugas yang dapat diselesaikan sebelum due
tanggal mereka jika setiap tugas diselesaikan dalam urutan yang diberikan oleh taskArray
, mulai dari initialTime
.
Algoritme untuk mengimplementasikan fungsi ini relatif mudah: beralih pada tugas di taskArray
. Untuk setiap tugas, tambahkan time
ke initialTime
. Jika waktu baru < due
, tambahkan importance
ke akumulator. Waktu disesuaikan dengan workPerDay terbalik. Sebelum mengembalikan akumulator, bagi dengan jumlah kepentingan tugas untuk dinormalisasi.
function weightedTasksOnTime(workPerDay, initialTime, taskArray) {
let simulatedTime = initialTime
let accumulator = 0;
for (task in taskArray) {
simulatedTime += task.time * (24 / workPerDay)
if (simulatedTime < task.due) {
accumulator += task.importance
}
}
return accumulator / totalImportance(taskArray)
}
Saya percaya masalah di atas dapat disederhanakan, dengan tetap mempertahankan intinya, dengan menghapus workPerDay
dan persyaratan normalisasi, untuk memberikan:
function weightedTasksOnTime(initialTime, taskArray) {
let simulatedTime = initialTime
let accumulator = 0;
for (task in taskArray) {
simulatedTime += task.time
if (simulatedTime < task.due) {
accumulator += task.importance
}
}
return accumulator
}
Pertanyaan ini membahas situasi di mana kode yang diuji bukan implementasi ulang dari algoritma yang ada. Jika kode adalah implementasi ulang, secara intrinsik memiliki mudah untuk memprediksi hasil, karena implementasi algoritma yang dipercaya bertindak sebagai ramalan uji alami.