Я часто працюю з дуже числовими / математичними програмами, де точний результат функції важко передбачити заздалегідь.
Намагаючись застосувати TDD з таким кодом, я часто вважаю, що писати код під тестом значно простіше, ніж писати одиничні тести для цього коду, тому що єдиний спосіб, який я знаю, щоб знайти очікуваний результат, - це застосувати сам алгоритм (чи в моєму головою, на папері або за комп’ютером). Це відчуває себе неправильно, оскільки я ефективно використовую тестований код для перевірки моїх тестових одиниць, а не навпаки.
Чи відомі методи написання одиничних тестів та застосування TDD, коли результат перевіреного коду важко передбачити?
(Реальний) приклад коду з важко передбачуваними результатами:
Функція, weightedTasksOnTimeяка, враховуючи кількість робіт, виконаних за день workPerDayв діапазоні (0, 24], поточний час initialTime> 0, і список завдань taskArray; кожне з часом заповнити властивість time> 0, термін dueі значення важливості importance; повертається нормоване значення в діапазоні [0, 1], що представляє важливість завдань, які можна виконати до їх dueдати, якщо кожне завдання, якщо виконане в порядку, заданому taskArray, починаючи з initialTime.
Алгоритм реалізації цієї функції відносно простий: ітерайте над завданнями в taskArray. Для кожного завдання додайте timeдо initialTime. Якщо новий час < due, додайте importanceдо акумулятора. Час регулюється за допомогою зворотного робочого дня. Перш ніж повернути акумулятор, розділіть їх на суму важливих завдань для нормалізації.
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
}
Це питання стосується ситуацій, коли тестований код не є повторною реалізацією існуючого алгоритму. Якщо код є повторною реалізацією, він по суті має легко передбачити результати, тому що існуючі надійні реалізації алгоритму виступають як природний тестовий оракул.