Подтвердить что ты не робот

Нетерминизм в модульном тестировании

Похоже, что во многих модульных тестах значения, параметризующие тест, либо испекаются самим тестом, либо объявляются предопределенным образом.

Например, вот тест, взятый из модульных тестов nUnit (EqualsFixture.cs):

[Test]
public void Int() 
{
    int val = 1;
    int expected = val;
    int actual = val;

    Assert.IsTrue(expected == actual);
    Assert.AreEqual(expected, actual);
}

Это имеет то преимущество, что является детерминированным; если вы один раз запустите тест, и он терпит неудачу, он будет продолжать сбой, пока код не будет исправлен. Однако вы заканчиваете тестирование только ограниченного набора значений.

Я не могу не чувствовать, что это пустая трата; точно такой же тест, вероятно, будет выполняться с теми же параметрами сотни, если не тысячи раз в течение всего жизненного цикла проекта.

Как насчет того, чтобы рандомизировать как можно больше вклада во все модульные тесты, чтобы каждый запуск показывал что-то новое?

В предыдущем примере возможно:

[Test]
public void Int() 
{
    Random rnd = new Random();
    int val = rnd.Next();
    int expected = val;
    int actual = val;
    Console.WriteLine("val is {0}", val);
    Assert.IsTrue(expected == actual);
    Assert.AreEqual(expected, actual);
}

(Если код ожидает строку, возможно, случайная строка, известная как действительная для конкретной функции, может использоваться каждый раз)

Преимущество будет заключаться в том, что чем больше раз вы запускаете тест, тем больший набор возможных значений, которые, как вы знаете, могут обрабатывать корректно.

Это полезно? Зло? Есть ли недостатки в этом? Я полностью упустил точку модульного тестирования?

Спасибо за ваши мысли.

4b9b3361

Ответ 1

Вы хотите, чтобы ваши модульные тесты повторялись, чтобы они всегда вели себя одинаково, если код не изменится. Затем, если код изменится и приведет к сбою unit test, вы можете исправить код, а unit test выполнил свою задачу. Более того, вы знаете, что код [вероятно] исправлен, когда unit test снова проходит.

Если случайные модульные тесты могут найти необычные ошибки, но это не обязательно. Если вы знаете, как работает код (сравните белый квадрат и черный ящик с подходом к тестированию), использование случайных значений никогда не должно показывать ничего, что хорошо подумали бы о неслучайных модульных тестах. И мне не хотелось бы, чтобы мне сказали "несколько раз запустить тесты, и эта ошибка должна появиться".

Ответ 2

То, что вы предлагаете, имеет большой смысл, если вы делаете это правильно. Вам не обязательно всегда слушать только обычную мудрость, которая говорит, что вы никогда не должны иметь детерминизм в своих тестах.

Что действительно важно, так это то, что каждый тест должен всегда выполнять один и тот же путь кода. Это не совсем то же самое.

Вы можете принять то, что я называю Ограниченный не-детерминизм в модульном тестировании. Это может привести вас к более спецификационно-ориентированному способу написания тестов.

Ответ 3

Тестирование должно охватывать ваши варианты использования, не более.

Посмотрите PEX.

Ответ 4

Большая проблема, с которой я сталкиваюсь, заключается в том, что, поскольку это случайное действие, это может не вызвать сбой, пока тест не будет запущен 200, 2000, 3000 или более раз. Если это терпит неудачу в течение 6007 месяцев или лет после того, как дело было написано, это по сути означает, что у вас была ошибка в течение нескольких месяцев или лет и она никогда не знала.

Вместо этого я думаю, что гораздо полезнее узнать ваши угловые случаи и проверить их все конкретно. Другими словами, подумайте о том, какие данные могут сломать ваш код и протестировать его.

Ответ 5

Вы тестируете Random или оператор равенства?

Мне кажется, что вы выберете типичные значения плюс граничные условия или перетащите весь набор Integer. Просто выбор случайных целых чисел не помогает ни с одним из подходов.

Чтобы ответить на ваш последний вопрос, в чем смысл модульного тестирования, я чувствую это: значение доказательства повторяемых результатов превышает стоимость написания тестов.

Ответ 6

Если ваше приложение не является детерминированным, вы тратите свое время на тестирование, если оно не является очень маленьким приложением.