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

А именно, у меня есть метод выборы n объекты из списка таким способом, которым % их соответствуют одному критерию, и b % встречает секунду и так далее. Упрощенный пример состоял бы в том, чтобы выбрать 5 объектов, где 50% имеют данное свойство со значением 'истинная', и 50%-я 'ложь'; 50% времени метод возвратили бы 2 истинных/3 false, и другие 50%, 3 истинной/2 лжи.

Статистически разговор, это означает, что более чем 100 выполнений, я должен получить приблизительно 250 истинной/250 лжи, но из-за случайности, 240/260 совершенно возможен.

Что лучший способ - к модульному тесту это? Я предполагаю, что даже при том, что технически 300/200 возможен, он должен, вероятно, провалить тест, если это происходит. Существует ли общепринятый допуск для случаев как это, и если так, как Вы определяете, каково это?

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

26
задан Flynn1179 18 June 2010 в 09:56
поделиться

9 ответов

Случайность и статистика не приветствуются в модульных тестах. Юнит-тесты должны всегда возвращать один и тот же результат. Всегда. Не в основном.

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


Дополнительные мысли:

Вы можете рассмотреть возможность изменения реализации, чтобы сделать ее более тестируемой. Постарайтесь получать как можно меньше случайных значений. Например, можно получить только одно случайное значение для определения отклонения от среднего распределения. Это было бы легко проверить. Если случайная величина равна нулю, вы должны получить именно то распределение, которое ожидаете в среднем. Если значение равно, например, 1.0, то вы отклоняетесь от среднего на некоторый определенный коэффициент, например, на 10%. Вы также можете реализовать некоторое гауссово распределение и т.д. Я знаю, что это не относится к данной теме, но если вы вольны реализовать это так, как вам хочется, подумайте о тестируемости.

22
ответ дан 28 November 2019 в 07:27
поделиться

Согласно имеющейся у вас статистической информации, в результате определите диапазон, а не конкретное отдельное значение.

4
ответ дан 28 November 2019 в 07:27
поделиться

Сначала вы должны знать, какое распределение должно произойти в результате вашего процесса генерации случайных чисел. В вашем случае вы генерируете результат, равный 0 или 1 с вероятностью -0,5. Это описывает биномиальное распределение с p = 0,5.

Учитывая размер выборки n, вы можете построить (как предлагалось ранее) доверительный интервал вокруг среднего. Вы также можете сделать различные утверждения о вероятности получения, например, 240 или меньше любого результата при n = 500.

Вы можете использовать предположение о нормальном распределении для значений N больше 20, если p не очень велико или не очень мало. В сообщении в Википедии есть больше об этом.

0
ответ дан 28 November 2019 в 07:27
поделиться

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

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

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

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

4
ответ дан 28 November 2019 в 07:27
поделиться

Мне кажется, здесь есть по крайней мере три различных вещи, которые вы хотите проверить:

  1. Правильность процедуры, которая генерирует выходные данные с использованием случайного источника
  2. Что распределение случайный источник - это то, что вы ожидаете.
  3. Распределение выходных данных - это то, что вы ожидаете.

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

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

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

Ожидаемое распределение для 3 будет во многом зависеть от того, что именно вы производите. Простой случай 50-50 в вопросе в точности эквивалентен проверке честной монеты , но, очевидно, другие случаи будут более сложными. Если вы можете определить, каким должно быть распределение, может помочь тест хи-квадрат .

4
ответ дан 28 November 2019 в 07:27
поделиться

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

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

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

Вы должны проверить распределение результатов в "одиночном" модульном тесте, т.е. чтобы результат был как можно ближе к желаемому распределению в любом отдельном запуске. Для вашего примера 2 true / 3 false - это нормально, 4 true / 1 false - не нормально.

Также можно написать тесты, которые выполняют метод, например, 100 раз и проверяют, что среднее значение распределений "достаточно близко" к желаемому. Это пограничный случай - выполнение больших партий может занять значительное количество времени, поэтому такие тесты лучше выполнять отдельно от "обычных" модульных тестов. Кроме того, как отмечает Стефан Штайнеггер, такой тест будет время от времени проваливаться, если вы определите "достаточно близко" более жестко, или начнет терять смысл, если вы определите порог слишком слабо. Так что это непростой случай...

2
ответ дан 28 November 2019 в 07:27
поделиться

Я думаю, что если бы у меня была такая же проблема, я, вероятно, построил бы доверительный интервал для обнаружения аномалий, если у вас есть некоторая статистика о среднем / stddev и т. Д. Итак, в вашем случае, если среднее ожидаемое значение равно 250, создайте 95% доверительный интервал вокруг среднего, используя нормальное распределение. Если результаты выходят за рамки этого интервала, вы не пройдете тест.

см. подробнее

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

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

0
ответ дан 28 November 2019 в 07:27
поделиться
Другие вопросы по тегам:

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