関数の正確な結果を事前に予測するのが難しい、非常に数値的/数学的なプログラムを頻繁に使用しています。
この種のコードで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
}
この質問は、テスト対象のコードが既存のアルゴリズムの再実装ではない状況に対処します。コードが再実装の場合、アルゴリズムの既存の信頼できる実装は自然なテストオラクルとして機能するため、本質的に結果を簡単に予測できます。