Это лучше иметь
- Детерминированный набор тестов, который приводит к успешному завершению тех же тестов
- Недетерминированный набор тестов, который потенциально может охватывать больше случаев
?
Пример: вы пишете набор тестов для тестирования функциональности контроллера в приложении MVC. Контроллер требует данные приложения из базы данных в качестве входных данных во время теста. Есть два варианта сделать это:
- Вы жестко задаете, какие строки из тестовой базы данных выбираются в качестве входных данных (например, 10-я и 412-я строки)
- Вы используете генератор случайных чисел для псевдослучайного выбора данных из базы данных (две строки выбираются генератором случайных чисел)
Первый является детерминированным: каждый прогон теста для одной и той же ревизии кода должен давать один и тот же результат. Второй недетерминированный: каждый запуск набора тестов может дать другой результат. Однако случайно выбранные данные могут быть более точным представлением крайних случаев данных. Это может имитировать пользователя, который лучше снабжает наши контроллеры непредсказуемыми данными?
Каковы причины, чтобы выбрать один над другим?
Ответы:
Когда каждый запуск комплекта тестов дает вам возможность давать разные результаты, тест почти полностью бесполезен - когда комплект показывает вам ошибку, у вас есть высокая вероятность, что вы не сможете ее воспроизвести, и когда вы попытаетесь исправить ошибка, вы не можете проверить, работает ли ваше исправление.
Поэтому, когда вы считаете, что вам нужно использовать какой-то генератор случайных чисел для генерации ваших тестовых данных, либо убедитесь, что вы всегда инициализируете генератор с одним и тем же начальным числом, либо сохраните ваши случайные тестовые данные в файле, прежде чем передавать их в свой тест, так что вы можете повторно запустить тест с точно такими же данными, что и ранее. Таким образом, вы можете превратить любой недетерминированный тест в детерминированный.
РЕДАКТИРОВАТЬ: Использование генератора случайных чисел для выбора некоторых тестовых данных ИМХО иногда является признаком того, что слишком ленив в выборе хороших тестовых данных. Вместо того, чтобы выбрасывать 100 000 случайно выбранных тестовых значений и надеяться, что этого будет достаточно, чтобы случайно обнаружить все серьезные ошибки, лучше использовать свой мозг, выбрать от 10 до 20 «интересных» случаев и использовать их для набора тестов. Это приведет не только к повышению качества ваших тестов, но и к гораздо более высокой производительности пакета.
источник
И детерминированный и недетерминированный имеют место
Я бы разделил их следующим образом:
Модульные тесты.
Они должны иметь детерминированные, повторяемые тесты с одинаковыми данными каждый раз. Модульные тесты сопровождают отдельные изолированные разделы кода и должны тестировать их детерминистическим образом.
Функциональные и входные стресс-тесты.
Они могут использовать недетерминированный подход со следующими оговорками:
источник
И то и другое.
Детерминированные и недетерминированные тесты имеют разные варианты использования и разные значения для вашего набора. Как правило, недетерминированный не может обеспечить ту же точность, что и детерминированный тест, который постепенно превращается в «недетерминированный тест, не имеющий никакой ценности». Это неверно Они могут быть менее точными, но они также могут быть гораздо шире, что имеет свои преимущества.
Давайте рассмотрим пример: вы пишете функцию, которая сортирует список целых чисел. Какие бы детерминированные юнит-тесты вы бы нашли полезным?
NaN
,INT_MIN
иINT_MAX
И это только функция сортировки! Конечно, вы можете утверждать, что некоторые из них не нужны, или что некоторые из них могут быть исключены с помощью неформальных рассуждений. Но мы инженеры, и мы видели неформальные рассуждения, взрывающиеся перед нами. Мы знаем, что мы недостаточно умны, чтобы полностью понимать системы, которые мы построили, или полностью держать сложность в наших головах. Вот почему мы пишем тесты в первую очередь. Добавление недетерминированного тестирования просто говорит о том, что мы не обязательно достаточно умны, чтобы априори знать все хорошие тесты. Добавляя полуслучайные данные в вашу функцию, вы с большей вероятностью найдете пропущенный крайний случай.
Конечно, это не исключает и детерминированного тестирования. Недетерминированное тестирование помогает находить ошибки в огромных рядах программы. Однако, как только вы нашли ошибки, вам нужен воспроизводимый способ показать, что вы их исправили. Так:
Обратите внимание, что это означает, что много твердых советов о модульных тестах не обязательно относятся к недетерминированным тестам. Например, что они должны быть быстрыми. Низкоуровневые тесты свойств должны быть быстрыми, но недетерминированный тест, такой как «симуляция случайного нажатия пользователем кнопок на вашем веб-сайте и проверка того, что вы никогда не получите ошибку 500», должен способствовать полноте над скоростью. Просто запустите такой тест независимо от процесса сборки, чтобы он не замедлял разработку. Например, запустите его в своем личном инсталляционном окне.
источник
Вы действительно не хотите детерминированного против недетерминированного.
То, что вы можете хотеть, это «всегда одно и то же» против «не всегда одно и то же».
Например, у вас может быть номер сборки, который увеличивается с каждой сборкой, а когда вам нужны случайные числа, вы инициализируете генератор случайных чисел с номером сборки в качестве начального числа. Поэтому при каждой сборке вы проводите тесты с разными значениями, что дает вам больше шансов найти ошибки.
Но как только ошибка найдена, все, что вам нужно сделать, это запустить тест с тем же номером сборки, и он воспроизводим.
источник