我经常使用非常数值/数学的程序,其中函数的确切结果很难预先预测。
在尝试将TDD与此类代码一起应用时,我经常发现编写被测代码比编写该代码的单元测试要容易得多,因为我知道找到预期结果的唯一方法是应用算法本身(无论头,纸上或通过计算机)。感觉不对,因为我正在有效地使用被测代码来验证单元测试,而不是相反。
当难以预测被测代码的结果时,是否存在用于编写单元测试和应用TDD的已知技术?
难以预测结果的(真实)代码示例:
返回weightedTasksOnTime
给定每天workPerDay
在(0,24]范围内完成的工作量,当前时间initialTime
> 0和任务列表的函数taskArray
;每个任务的完成属性时间time
> 0,到期日due
和重要性值importance
;返回[0,1]范围内的标准化值,表示due
如果每个任务按taskArray
,给出的顺序完成,则可以在其日期之前完成的任务的重要性initialTime
。
实现此功能的算法相对简单:对中的任务进行迭代taskArray
。对于每个任务,添加time
到initialTime
。如果新时间< due
,则添加importance
到累加器。时间是通过反向workPerDay来调整的。返回累加器之前,请除以任务重要性之和以进行归一化。
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)
}
我相信可以通过删除workPerDay
和规范化要求来简化上述问题,同时保持其核心,从而得出:
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
}
这个问题解决了被测代码不是现有算法的重新实现的情况。如果代码是重新实现的,则其本质上很容易预测结果,因为该算法的现有可信实现充当自然的测试预言。