Каковы недостатки использования случайных значений в модульном тестировании?

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

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

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

Есть ли недостатки?

30
задан Fermi paradox 10 July 2019 в 05:51
поделиться

7 ответов

Недостатки

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

Во-вторых, часто невозможно точно определить ожидаемый ответ. Если вы знаете ответ на основе входных данных, то велика вероятность, что вы просто копируете тестируемую логику (подумайте об этом - если входные данные случайны, откуда вы знаете ожидаемый выход?). В результате вам, возможно, придется обменять очень специфические утверждения (значение должно быть x) на более общие утверждения, проверяющие вменяемость (значение должно быть между y и z).

В-третьих, если нет широкого диапазона входов и выходов, вы часто можете покрыть тот же диапазон, используя хорошо подобранные значения в стандартных модульных тестах с меньшей сложностью. Например, выберите числа -max, (-max + 1), -2, -1, 0, 1, 2, max-1, max. (или любое другое, интересное для алгоритма).

Положительные стороны

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

Дополнительные приемы

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

40
ответ дан 27 November 2019 в 23:37
поделиться

Они случайны.

(Ваш тест может случайно сработать, даже если ваш код сломан.)

8
ответ дан 27 November 2019 в 23:37
поделиться

Кроме того, вы не сможете воспроизводить тесты много раз. Юнит-тест должен выполняться точно так же с заданными параметрами.

7
ответ дан 27 November 2019 в 23:37
поделиться

Намного лучше иметь модульные тесты, которые на 100% воспроизводятся и включают все крайние случаи. Например, нулевой тест, отрицательные, положительные, слишком большие числа, слишком маленькие числа и т. Д. Если вы хотите включить тесты со случайными значениями в дополнение ко всем крайним случаям и нормальным случаям, это будет нормально. Однако я не уверен, что вы получите много пользы от потраченного времени. Наличие всех нормальных случаев и крайних случаев должно справиться со всем. Остальное - «подливка».

3
ответ дан 27 November 2019 в 23:37
поделиться

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

3
ответ дан 27 November 2019 в 23:37
поделиться

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

Если у вас уже есть представление о диапазоне значений, которые вы хотите проверить, то вам следует либо (1) создать отдельный тест для каждого значения в диапазоне, либо (2) перебрать весь набор значений и сделать утверждение на каждой итерации. Быстрый и довольно глупый пример...

for($i = 0; $i < 10; $i++)
  $this->assertEquals($i + 1, Math::addOne($i));

Можно сделать нечто подобное с кодировками символов. Например, перебрать набор символов ASCII и проверить все эти сумасшедшие символы на одной из ваших функций работы с текстом.

1
ответ дан 27 November 2019 в 23:37
поделиться

Вам нужно запомнить, какие случайные числа вы генерировали при проверке.

Пример.

Username= "username".rand();
Save_in_DB("user",Username); // To save it in DB
Verify_if_Saved("user",Username); 
0
ответ дан 27 November 2019 в 23:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: