私のお気に入りのミューテーションテストフレームワーク( NinjaTurtles )用の「OffBy One」ミューテーションテスターを作成する過程で、実装の正確さを確認する機会を提供するために、次のコードを作成しました。
public int SumTo(int max)
{
int sum = 0;
for (var i = 1; i <= max; i++)
{
sum += i;
}
return sum;
}
これは十分に単純なように思えますが、IL内のすべてのリテラル整数定数を変更しようとしても問題が発生することはありませんでした。結局のところ、3つ(、、、、および)しかあり0
ませ1
ん++
。
間違い!
最初の実行で、この特定のインスタンスでは機能しないことが非常に明白になりました。なんで?コードをに変更するため
public int SumTo(int max)
{
int sum = 0;
for (var i = 0; i <= max; i++)
{
sum += i;
}
return sum;
}
合計に0(ゼロ)を追加するだけで、これは明らかに効果がありません。複数のセットだった場合は別の話ですが、この場合はそうではありませんでした。
これで、整数の合計を計算するためのかなり簡単なアルゴリズムがあります
sum = max * (max + 1) / 2;
いずれかの定数から1を加算または減算するとエラーが発生するため、ミューテーションは簡単に失敗する可能性があります。(それを考えるとmax >= 0
)
したがって、この特定のケースでは問題が解決しました。それは私が突然変異のテストに望んでいたことをしませんでしたが、それは私が失ったときに何が起こるかをチェックすることでした++
-事実上無限ループ。しかし、それは別の問題です。
だから-私の質問: 0または1から始まるループが、同様の方法でリファクタリング(テスト中またはテスト中のコード)できない「1つずつ突然変異」テストの失敗につながる可能性がある、些細なまたは重要なケースはありますか?(例をお願いします)
注:ミューテーションが適用された後にテストスイートが合格すると、ミューテーションテストは失敗します。
更新:ささいなことではないが、テストがリファクタリングされて失敗する可能性があるものの例は次のようになります
public int SumArray(int[] array)
{
int sum = 0;
for (var i = 0; i < array.Length; i++)
{
sum += array[i];
}
return sum;
}
このコードに対するミューテーションテストは、指定したテスト入力がであった場合にに変更var i=0
すると失敗します。ただし、テスト入力をに変更すると、ミューテーションテストは失敗します。したがって、リファクタリングが成功すると、テストが証明されます。var i=1
new[] {0,1,2,3,4,5,6,7,8,9}
new[] {9,8,7,6,5,4,3,2,1,0}