Я за случайные тесты и пишу их. Однако вопрос о том, подходят ли они в конкретной среде сборки и в какие наборы тестов они должны быть включены, является более нюансированным вопросом.
Запускать локально (например, в течение ночи на вашем устройстве разработки) рандомизированные тесты обнаружили ошибки как очевидные, так и неясные. Непонятные из них достаточно загадочны, так что я думаю, что случайное тестирование действительно было единственно реалистичным, чтобы избавиться от них. В качестве теста я взял одну трудно обнаруживаемую ошибку, обнаруженную при рандомизированном тестировании, и попросил полдюжины разработчиков взломать функцию (около десятка строк кода), где она произошла. Никто не смог его обнаружить.
Многие из ваших аргументов против рандомизированных данных являются разновидностями «тест не воспроизводим». Однако хорошо написанный рандомизированный тест захватит начальное число, использованное для запуска рандомизированного начального значения, и выдаст его при неудаче. В дополнение к тому, что вы можете повторить тест вручную, это позволяет вам тривиально создать новый тест, который тестирует конкретную проблему, жестко закодировав начальное значение для этого теста. Конечно, было бы лучше написать вручную явный тест, охватывающий этот случай, но лень имеет свои достоинства, и это даже позволяет вам по существу автоматически генерировать новые тестовые случаи из неудачного начального числа.
Однако, одно замечание, которое я не могу обсуждать, это то, что это ломает системы сборки. Большинство тестов сборки и непрерывной интеграции предполагают, что тесты будут выполнять одно и то же каждый раз. Таким образом, тест, который случайно провалится, создаст хаос, случайно провалится и покажет пальцем на изменения, которые были безвредными.
Решение, таким образом, состоит в том, чтобы по-прежнему запускать рандомизированные тесты как часть тестов сборки и CI, но запускать их с фиксированным начальным числом для фиксированного числа итераций . Следовательно, тест всегда делает одно и то же, но все же исследует кучу входного пространства (если вы запускаете его для нескольких итераций).
Локально, например, при изменении соответствующего класса, вы можете запускать его для дополнительных итераций или с другими семенами. Если рандомизированное тестирование становится все более популярным, вы можете даже представить конкретный набор тестов, которые, как известно, являются случайными, которые могут выполняться с разными начальными значениями (следовательно, с увеличением охвата с течением времени), и где сбои не означают одно и то же как детерминированные системы CI (т. е. прогоны не связаны 1: 1 с изменениями кода, поэтому вы не указываете на конкретное изменение в случае неудачи).
Многое можно сказать о рандомизированных тестах, особенно хорошо написанных, поэтому не спешите их отбрасывать!