Тестирование колоды карт тасовкой - PullRequest
8 голосов
/ 18 сентября 2009

У меня есть класс PlayingCard, который представляет конкретную игральную карту. У меня есть другой класс, Deck, который содержит список объектов PlayingCard. В колоде есть метод shuffle(), который рандомизирует порядок карт.

Я хотел бы написать несколько тестов для метода shuffle (), но я немного растерялся. Я бы предпочел, чтобы тест не заботился о внутренностях только о том, как выполняется перемешивание, но я хочу, чтобы они были хорошими тестами.

Как мне лучше всего пройти юнит-тест, когда речь идет о случайности?

Ответы [ 7 ]

10 голосов
/ 18 сентября 2009

Одним из подходов является проведение статистических тестов; после каждой случайной проверки правильности (набор карточек не должен был изменяться, только порядок), и собирать статистику о некоторых случайных переменных («позиция 7 алмазов», «5 из булавы до или после «восьмерки сердец» и т. п.) для проверки после подходящего количества перетасовок с помощью t-критерия Стьюдента и других статистических подходов к проверке гипотез.

5 голосов
/ 18 сентября 2009

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

Это тот случай, когда внедрение метода в ваш класс Deck () во время тестирования может сделать вашу функцию перемешивания детерминированной.

Создайте свой класс для использования функции random () по умолчанию, но для использования предопределенной функции генерации чисел при введении. Например, в Python вы можете сделать:

class Deck():
   def __init__(self, rand_func = random.random):
      self._rand = rand_func
   def rand(self):
      return self._rand()

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

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

Что касается ответов других, связанных со статистическим моделированием: я думаю, что это тесты приемлемого уровня, чтобы доказать правильность алгоритма "shuffle", но он не детерминистически тестирует реализацию функции shuffle ().

5 голосов
/ 18 сентября 2009

У меня нет особых идей об этом модульном тестировании, но есть краткое замечание об используемом вами алгоритме. Очень легко наивно и по незнанию создать необъективный алгоритм перемешивания. Нет необходимости заново изобретать колесо - тасовка Фишера-Йейтса обеспечит беспристрастный тасование, если оно реализовано правильно.

Если вы не выполняете FY должным образом, вы можете легко попасть в ловушку:

  • Возьмите каждую карту i и обменяйте ее на другую случайную карту j в колоде, где j может быть любой картой, даже одной из уже посещенных. позиция. Этот является предвзятым тасованием.
  • Получив выходные данные ГСЧ mod 52, чтобы получить случайные позиции карты. Также приводит к небольшому смещению.
1 голос
/ 18 сентября 2009

Несколько лет назад в списке TDD группы Yahoo возникла исчерпывающая (или исчерпывающая) тема. У Рона Джеффриса есть некоторые полезные идеи , но лучше всего начинать с с вершины .

1 голос
/ 18 сентября 2009

Хороший вопрос. Во-первых, абсолютный тест «пройдено / не пройдено»: после перемешивания мультимножество (например, сравнение после сортировки) должно быть неизменным.

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

С вероятностью .0000001% вероятность того, что при 10000 тасовках конкретная карта окажется в одном из заданных 52 слотов меньше (1-е) / 52 или больше (1 + е) / 52. (для небольшого электронного я не знаю, как его вычислить).

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

Что касается перетасовки; одна общая ошибка состоит в том, чтобы сделать это:

для меня от 1..52:
выберите случайное число j из 1 .. 52 и поменяйте местами карту i с картой j ( неправильно )

Это не дает вам никакой перестановки с равной вероятностью; это, однако, делает:

для меня от 1..52:
выберите случайное число j из i .. 52 и поменяйте местами карту i с картой j ( вправо )

0 голосов
/ 18 сентября 2009

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

0 голосов
/ 18 сентября 2009
  1. Создать список.
  2. Создать полную копию этого списка.
  3. Перемешать первый список.
  4. Утвердить list1! = List2

Добавьте дополнительные описательные тесты по мере необходимости. Качество случайности, случайность и т.д ...

Как указал Алекс Мартелли, вы можете выполнить статистический анализ сортировки, чтобы подтвердить, что она отсортирована в ожидаемой степени.

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

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

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