В процессе написания тестера мутаций "Off By One" для моей любимой среды тестирования мутаций (NinjaTurtles) я написал следующий код, чтобы дать возможность проверить правильность моей реализации:
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, может привести к сбою теста "изменение на единицу", которое не может быть исправлено (тестируемый код или test) аналогичным образом? (примеры, пожалуйста)
Примечание. Тесты на мутацию не проходят, если набор тестов проходит после применения мутации.
Обновление: пример чего-то менее тривиального, но что-то, что можно было бы отрефакторировать так, чтобы он не прошел, будет следующее
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}
, и проверка мутации завершится неудачно. Итак, успешный рефакторинг - это доказательство тестирования.