Ich arbeite häufig mit sehr numerischen / mathematischen Programmen, bei denen es schwierig ist, das genaue Ergebnis einer Funktion vorherzusagen.
Bei dem Versuch, TDD mit dieser Art von Code anzuwenden, ist das Schreiben des zu testenden Codes häufig wesentlich einfacher als das Schreiben von Komponententests für diesen Code, da ich das erwartete Ergebnis nur mit der Anwendung des Algorithmus selbst (unabhängig davon, ob in meinem Kopf, auf Papier oder am Computer). Dies fühlt sich falsch an, da ich den getesteten Code effektiv verwende, um meine Komponententests zu verifizieren, anstatt umgekehrt.
Gibt es bekannte Techniken zum Schreiben von Komponententests und zum Anwenden von TDD, wenn das Ergebnis des zu testenden Codes schwer vorherzusagen ist?
Ein (reales) Beispiel für Code mit schwer vorhersagbaren Ergebnissen:
Eine Funktion weightedTasksOnTime
, die eine Menge an Arbeit pro Tag getan gegeben workPerDay
in Bereich (0, 24], die aktuelle Uhrzeit initialTime
> 0, und eine Liste von Aufgaben taskArray
, die jeweils mit einer Zeit abzuschließen Eigentum time
> 0, Fälligkeit due
und Wichtigkeitswert importance
; Renditen Ein normalisierter Wert im Bereich [0, 1], der die Wichtigkeit von Aufgaben darstellt, die vor ihrem due
Datum erledigt werden können, wenn jede Aufgabe in der von angegebenen Reihenfolge erledigt wird taskArray
, beginnend mit initialTime
.
Der Algorithmus zum Implementieren dieser Funktion ist relativ einfach: Iterieren Sie über Tasks in taskArray
. Für jede Aufgabe hinzufügen time
zu initialTime
. Wenn die neue Zeit <ist due
, fügen Sie importance
sie einem Akkumulator hinzu. Die Zeit wird durch inverse workPerDay angepasst. Teilen Sie vor der Rückgabe des Akkus die zu normalisierenden Aufgabenbedeutungen durch die Summe.
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)
}
Ich glaube, dass das obige Problem unter Beibehaltung seines Kerns vereinfacht werden kann, indem workPerDay
die Normierungsanforderung beseitigt wird, um Folgendes zu ergeben:
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
}
Diese Frage befasst sich mit Situationen, in denen der zu testende Code keine Neuimplementierung eines vorhandenen Algorithmus ist. Wenn es sich bei Code um eine Neuimplementierung handelt, lassen sich die Ergebnisse von sich aus leicht vorhersagen, da vorhandene vertrauenswürdige Implementierungen des Algorithmus als natürliches Testorakel fungieren.