2012-06-11 14 views
5

Existen algunos dominios de aplicación (por ejemplo, GameDev) en los que se deben crear muchas funciones utilizando valores aleatorios para producir su salida. Uno de los ejemplos se presenta a continuación:¿Cómo validar la corrección de funciones que usan al azar?

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 

Esta función genera la caída del elemento en función de varias operaciones aleatorias. El problema aparece si desea validar automáticamente la corrección de esta función. Los valores generados no son deterministas y la escritura de pruebas de regresión parece ser imposible.

Mis preguntas son:

  1. Es esto posible escribir pruebas de regresión útiles para este tipo de funciones ?
  2. ¿Hay algún método general para crear otro tipo de pruebas en este caso?
+4

Hay libros enteros escritos sobre este tema. Ejemplo: http://www.johndcook.com/Beautiful_Testing_ch10.pdf –

+1

Burlarse del RNG para entregar resultados conocidos (y luego probar con productos específicos para los cuales se conoce el resultado deseado) es un enfoque. –

Respuesta

3

Uno de unidad de pruebas útiles se presenta a continuación:

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 

valida firma de función, cubre todas las líneas de código (buena probabilidad) de función y pasará en 99,999% de los casos. También se validó que la función produce alguna caída de al menos una desde 1000 y en ocasiones no genera caída. 0.2 es la probabilidad de una caída de un artículo.

2

Volvería a escribir la función para usar la inyección de dependencia (el generador de números aleatorios se pasa como un parámetro a la función). Luego puede pasar un simulacro de un generador de números aleatorios para probar su función con diferentes entradas determinísticas "aleatorias".

Por supuesto, también puede probar sus afirmaciones que no dependen de los resultados de la llamada al azar. Tales como:

  • Las funciones devuelven None o a dict con las teclas "type" y "letter".
  • Si se devuelve un diccionario, los valores son del tipo y rango apropiados.

Nunca escribiría una prueba de unidad que tenga resultados no deterministas, incluso 1 en mil. Me preocupo por cada falla en la prueba, y los resultados estocásticos serían inquietantes. Sería mejor que encapsulara su aleatoriedad, de modo que la función se pueda probar independientemente del generador de números aleatorios.