Tôi thường xuyên làm việc với các chương trình số / toán học, trong đó kết quả chính xác của hàm rất khó dự đoán trước.
Khi thử áp dụng TDD với loại mã này, tôi thường thấy việc viết mã theo thử nghiệm dễ dàng hơn đáng kể so với viết thử nghiệm đơn vị cho mã đó, bởi vì cách duy nhất tôi biết để tìm kết quả mong đợi là áp dụng thuật toán (cho dù là của tôi đầu, trên giấy, hoặc bằng máy tính). Điều này cảm thấy sai, bởi vì tôi đang sử dụng hiệu quả mã được kiểm tra để xác minh các bài kiểm tra đơn vị của mình, thay vì cách khác.
Có các kỹ thuật đã biết để viết bài kiểm tra đơn vị và áp dụng TDD khi kết quả của mã được kiểm tra khó dự đoán không?
Một ví dụ (thực tế) về mã với kết quả khó dự đoán:
Một hàm weightedTasksOnTime
, với một lượng công việc được thực hiện mỗi ngày workPerDay
trong phạm vi (0, 24], thời gian hiện tại initialTime
> 0 và danh sách các nhiệm vụ taskArray
, mỗi lần có một thời gian để hoàn thành thuộc tính time
> 0, ngày đáo hạn due
và giá trị quan trọng importance
; một giá trị được chuẩn hóa trong phạm vi [0, 1] thể hiện tầm quan trọng của các nhiệm vụ có thể hoàn thành trước due
ngày của chúng nếu mỗi tác vụ nếu được hoàn thành theo thứ tự được đưa ra bởi taskArray
, bắt đầu từ initialTime
.
Thuật toán để thực hiện chức năng này tương đối đơn giản: lặp qua các tác vụ trong taskArray
. Đối với mỗi nhiệm vụ, thêm time
vào initialTime
. Nếu thời gian mới < due
, hãy thêm importance
vào một bộ tích lũy. Thời gian được điều chỉnh bởi công việc nghịch đảoPerDay. Trước khi trả lại bộ tích lũy, chia cho tổng số các nhiệm vụ quan trọng để bình thường hóa.
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)
}
Tôi tin rằng vấn đề trên có thể được đơn giản hóa, trong khi vẫn duy trì cốt lõi của nó, bằng cách loại bỏ workPerDay
và yêu cầu chuẩn hóa, để đưa ra:
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
}
Câu hỏi này giải quyết các tình huống trong đó mã được kiểm tra không phải là triển khai lại thuật toán hiện có. Nếu mã là một triển khai lại, về bản chất nó có thể dễ dàng dự đoán kết quả, bởi vì các triển khai đáng tin cậy hiện có của thuật toán hoạt động như một lời tiên tri thử nghiệm tự nhiên.