Tweeted twitter.com/StackSoftEng/status/1051352067183431681 occurred Oct 14 '18 at 6:00 5 deleted 14 characters in body edited Oct 11 '18 at 14:31 Robert Harvey♦ 172k4747 gold badges407407 silver badges615615 bronze badges 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 occurred Oct 10 '18 at 20:55 4 added 293 characters in body edited Oct 8 '18 at 7:21 PaintingInAir 71922 gold badges33 silver badges1111 bronze badges 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 edited Oct 7 '18 at 23:08 PaintingInAir 71922 gold badges33 silver badges1111 bronze badges 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 edited Oct 7 '18 at 23:00 PaintingInAir 71922 gold badges33 silver badges1111 bronze badges 1 asked Oct 7 '18 at 22:06 PaintingInAir 71922 gold badges33 silver badges1111 bronze badges