2009-09-18 6 views
8

Tengo una tarjeta de juego de clase que representa una carta de juego en particular. Tengo otra clase, Deck, que contiene una lista de objetos de PlayingCard. La plataforma tiene un método shuffle() que aleatoriza el orden de la tarjeta.Prueba de barajador de cartas

me gustaría escribir algunas pruebas unitarias para el método de reproducción aleatoria(), pero estoy en un poco de una pérdida. Prefiero que la prueba no se preocupe por las partes internas de cómo se hace la reproducción aleatoria, pero quiero que sean buenas pruebas.

¿Cuál es la mejor unidad de prueba cuando se trata de aleatoriedad?

+1

Una idea sería ejecutar el shuffler en un mazo ordenado y ejecutar un algoritmo de distancia para ver cómo "lejos" sale el shuffle; y ejecute continuamente y compare con permutaciones previas de regreso a un cierto punto (digamos 10-12 mezclas con requisitos degradantes de distancia) y luego compare esos valores con la diferencia óptima; sin embargo, usted tendrá que probar y obtener esos números usted mismo. – Corazu

Respuesta

10

Un enfoque es realizar pruebas estadísticas; después de cada comprobación aleatoria para la corrección (el conjunto de tarjetas no deberán haber sido cambiado, sólo el orden), y recoger información sobre algunas variables aleatorias ("posición del 7 de diamantes" ", es el 5 de tréboles antes o después de el 8 de corazones ", y similares) para ser probado después de un número adecuado de mezclas por Student's t-test y otros enfoques de prueba de hipótesis estadísticas.

+0

Buena recomendación. –

+0

Tx @Ty, así que si te gusta ¿por qué no votar? -) –

0
  1. crear una lista.
  2. Crea una copia profunda de esa lista.
  3. Baraja la primera lista.
  4. Assert lista1! = Lista2

Añadir pruebas más descriptivos como sea necesario. Calidad de la reproducción aleatoria, aleatoriedad, etc.

Como señaló Alex Martelli, puede realizar un análisis estadístico de la clasificación para confirmar que esté ordenada al grado que espera.

El mejor resultado es que cada posición de la tarjeta ha cambiado. Es decir, cada una de las 52 cartas ahora está en una nueva posición. Puede tomar mi enfoque anterior, registrar la cantidad de elementos que son diferentes y establecer un umbral para la prueba.

Espere que al menos 20 tarjetas estén en nuevas posiciones. Cree la lista, cópiela, ordénela y luego compárela. Si el resultado es menos de 20, falla, de lo contrario pasará.

+0

Hay una pequeña posibilidad de que el pedido sea el mismo después de barajar. –

+0

Digamos que la probabilidad de que el cambio aleatorio devuelva la misma lista que se le dio es p. Luego, 100% - p del tiempo, esta prueba funcionará correctamente. Ahora importa lo que hagas, siempre habrá una p. Puede reducirlo al volver a ejecutar en caso de falla, pero eso le costará más tiempo de prueba. Lo cual generalmente se considera algo malo. –

1

Una buena pregunta. En primer lugar, una prueba de aprobación/falla absoluta: después de la mezcla, el multiset (por ejemplo, comparar después de la clasificación) no debe modificarse.

Para probar la aleatoriedad, usted tiene que hacer suficientes baraja que la probabilidad de una falsa fracaso "no lo suficientemente aleatoria" es extremadamente pequeña. Por ejemplo:

Hay un .0000001% de posibilidades de que en 10000 mezclas, que una carta en particular se encuentre en una de las 52 ranuras dadas menor que (1-e)/52 o mayor que (1 + e) ​​/ 52 . (para algunos pequeños e, no sé cómo calcularlo).

un programa correcto puede "fallar" una prueba de este tipo, pero no debe dejar muy a menudo.

Con respecto a barajar; un fallo común es hacer esto:

para i desde 1..52:
elija un j azar de ..52 y canjear la tarjeta i con la tarjeta j (incorrecta)

Eso no le da ninguna permutación con igual probabilidad; esto, sin embargo, hace:

para i de 1..52:
elegir un j al azar de i tarjeta ..52 y de intercambio i con la tarjeta de j (derecho)

5

I don' Tengo ideas particulares sobre la prueba de unidad esto, pero una nota rápida sobre el algoritmo que utiliza. Es muy fácil crear de forma ingenua y sin saberlo un algoritmo aleatorio sesgado. No es necesario reinventar la rueda — Fisher-Yates shuffle garantizará una reproducción ordenada, si se implementa correctamente.

Hay trampas fáciles que puede pegarle si no se hace correctamente el AF:

  • Tome cada tarjeta i e intercambiarlo con otra carta al azar j en la cubierta donde j puede ser cualquier carta, incluso una desde una posición ya visitada. Esta es una mezcla aleatoria sesgada.
  • Tomando la salida de un RNG mod 52 para obtener posiciones de tarjeta al azar. También conduce a un ligero sesgo.
-2

Como no lo he probado, no puedo decir inmediatamente qué tan práctico es, pero debería ser posible hacer pruebas unitarias con cubiertas pequeñas y un generador de números aleatorios determinístico especial, ejecutado de manera el mezclador debe producir cada permutación posible una vez.

1

Hubo el tema de un hilo exhaustivo (o agotador) en la lista de TDD de Yahoo Groups hace unos años. Ron Jeffries tiene algunos useful insights pero pero es mejor comenzar en the top.

5

Su objetivo es probar shuffle(). Como sabes cómo construiste shuffle(), sería una prueba de unidad determinista de tu baraja inicial frente a la baraja barajada si pudieras conocer la serie de números generados.

Este es un caso donde inyectar un método en su clase Deck() durante la prueba puede hacer que su función de mezcla sea determinista.

Cree su clase para usar la función aleatoria() por defecto pero para usar una función de generación de números predeterminada cuando se inyecte. Por ejemplo, en Python que puede hacer:

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

Cuando el simple uso de la cubierta sin argumentos, se obtiene el número aleatorio se esperaba. Pero si crea su propia función de números aleatorios, puede generar su secuencia predeterminada de números.

Con esta construcción, ahora puede construir una plataforma inicial (el tamaño que desee) y una lista de números aleatorios (de nuevo, cualquiera que sea el tamaño que necesite) y sabrá qué esperar como salida. Debido a que shuffle() no cambia entre la versión inyectada y la versión verdaderamente aleatoria, puede realizar una prueba unitaria aleatoria() determinista y, sin embargo, tener un comportamiento aleatorio en el tiempo de ejecución. Incluso puede generar múltiples secuencias de números diferentes si hay casos de esquina que desea probar.

Con respecto a las respuestas del otro que implican modelos estadísticos: creo que son pruebas de nivel de aceptación para probar la exactitud del algoritmo "aleatorio", pero no determinísticamente prueba la implementación de la función shuffle().

Cuestiones relacionadas