2012-06-11 1 views
5

Есть некоторые области приложений (например, GameDev), в которых необходимо создать множество функций с использованием случайных значений для вывода их результатов. Один из примеров приведен ниже:Как проверить правильность функций, которые используются случайным образом?

def generate_key(monster_key_drop_coef): 
    key_letters = string.ascii_uppercase 
    rand = random.random() 
    if monster_key_drop_coef < rand: 
     return None 

    button = {} 
    button["type"] = random.choice([1,2,3]) 
    button["letter"] = random.choice(key_letters) 
    return button 

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

Мои вопросы:

  1. Возможно ли это писать полезные тесты регрессии для этого типа функций?
  2. Есть ли общий подход для создания некоторых других типов тестов в этом случае?
+4

На эту тему написаны целые книги. Пример: http://www.johndcook.com/Beautiful_Testing_ch10.pdf –

+1

Излучение ГСЧ для доставки известных результатов (а затем тестирование с конкретными выходами, для которых известен желаемый результат) является одним из подходов. –

ответ

3

Одним из полезных юнит-тестов представлены ниже:

def test_generate_key(): 
    button_list = [] 
    for _ in range(1, 1000): 
     button_list.append(generate_key(0.2)) 

    is_all_none = True 
    is_not_none = False 
    for key in button_list: 
     is_all_none &= (key is None) 
     is_not_none |= (key is not None) 

    assert is_all_none == False 
    assert is_not_none == True 

Он проверяет сигнатуру функции, охватывают все строки кода (хорошая вероятность) функция и будет проходить в 99.999% случаев. Также проверяется, что функция производит некоторое падение по крайней мере одного из 1000 и иногда не генерирует падение. 0.2 - вероятность падения предмета.

2

Я бы переписал функцию для использования инъекции зависимостей (генератор случайных чисел передается в качестве параметра функции). Затем вы можете передать макет генератора случайных чисел, чтобы проверить вашу функцию с различными детерминированными «случайными» входами.

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

  • Функции возвращают None или dict с ключами «type» и «letter».
  • Если словарь возвращается, значения имеют соответствующий тип и диапазон.

Я бы никогда не написал unittest, который имеет недетерминированные результаты, даже 1 из тысячи. Меня волнует каждый провал теста, и стохастические результаты будут тревожными. Вам лучше было бы инкапсулировать вашу случайность, чтобы функция могла быть проверена независимо от генератора случайных чисел.

Смежные вопросы