Tweeted twitter.com/StackSoftEng/status/1051352067183431681
5 deleted 14 characters in body
source | link

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

Edit: A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I believe the above problem can be simplified, while maintaining its core, by removing workPerDay and the normalization requirement, to give:

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
}

Edit 2: This question addresses situations where the code under test is not a re-implementation of an existing algorithm. If code is a re-implementation, it intrinsically has easy to predict results, because existing trusted implementations of the algorithm act as a natural test oracle.

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

Edit: A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I believe the above problem can be simplified, while maintaining its core, by removing workPerDay and the normalization requirement, to give:

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
}

Edit 2: This question addresses situations where the code under test is not a re-implementation of an existing algorithm. If code is a re-implementation, it intrinsically has easy to predict results, because existing trusted implementations of the algorithm act as a natural test oracle.

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I believe the above problem can be simplified, while maintaining its core, by removing workPerDay and the normalization requirement, to give:

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
}

This question addresses situations where the code under test is not a re-implementation of an existing algorithm. If code is a re-implementation, it intrinsically has easy to predict results, because existing trusted implementations of the algorithm act as a natural test oracle.

    Question Protected by gnat
4 added 293 characters in body
source | link

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

Edit: A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I believe the above problem can be simplified, while maintaining its core, by removing workPerDay and the normalization requirement, to give:

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
}

Edit 2: This question addresses situations where the code under test is not a re-implementation of an existing algorithm. If code is a re-implementation, it intrinsically has easy to predict results, because existing trusted implementations of the algorithm act as a natural test oracle.

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

Edit: A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I believe the above problem can be simplified, while maintaining its core, by removing workPerDay and the normalization requirement, to give:

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
}

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

Edit: A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I believe the above problem can be simplified, while maintaining its core, by removing workPerDay and the normalization requirement, to give:

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
}

Edit 2: This question addresses situations where the code under test is not a re-implementation of an existing algorithm. If code is a re-implementation, it intrinsically has easy to predict results, because existing trusted implementations of the algorithm act as a natural test oracle.

3 added 505 characters in body
source | link

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

Edit: A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I believe the above problem can be simplified, while maintaining its core, by removing workPerDay and the normalization requirement, to give:

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
}

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

Edit: A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I frequently work with very numeric / mathematical programs, where the exact result of a function is difficult to predict in advance.

In trying to apply TDD with this kind of code, I often find writing the code under test significantly easier than writing unit tests for that code, because the only way I know to find the expected result is to apply the algorithm itself (whether in my head, on paper, or by the computer). This feels wrong, because I am effectively using the code under test to verify my unit tests, instead of the other way around.

Are there known techniques for writing unit tests and applying TDD when the result of the code under test is difficult to predict?

Edit: A (real) example of code with difficult to predict results:

A function weightedTasksOnTime that, given an amount of work done per day workPerDay in range (0, 24], the current time initialTime > 0, and a list of tasks taskArray; each with a time to complete property time > 0, due date due, and importance value importance; returns a normalized value in range [0, 1] representing the importance of tasks that can be completed before their due date if each task if completed in the order given by taskArray, starting at initialTime.

The algorithm to implement this function is relatively straightforward: iterate over tasks in taskArray. For each task, add time to initialTime. If the new time < due, add importance to an accumulator. Time is adjusted by inverse workPerDay. Before returning the accumulator, divide by sum of task importances to normalize.

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)
}

I believe the above problem can be simplified, while maintaining its core, by removing workPerDay and the normalization requirement, to give:

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
}
2 Added an example as suggested
source | link
1
source | link