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

Какой лучший способ для unit test кода, который генерирует случайный вывод?

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

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

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

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

4b9b3361

Ответ 1

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

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


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

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

Ответ 2

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

Ответ 3

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

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

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

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

Ответ 4

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

  • Правильность процедуры, которая генерирует вывод с использованием случайного источника
  • Что распределение случайного источника - это то, что вы ожидаете
  • То, что распределение вывода - это то, что вы ожидаете

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

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

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

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

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

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

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

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