Pregunta

Me gustaría probar una función con una tupla de un conjunto de casos marginales y valores normales.Por ejemplo, al probar una función que devuelve true siempre que me dieran tres longitudes que forman un triángulo válido, tendría casos específicos, números negativos/pequeños/grandes, valores a punto de desbordarse, etc.;Es más, el objetivo principal es generar combinaciones de estos valores, con o sin repetición, para obtener un conjunto de datos de prueba.

(inf,0,-1), (5,10,1000), (10,5,5), (0,-1,5), (1000,inf,inf),
...

Como nota:De hecho, sé la respuesta a esto, pero podría ser útil para otros y un desafío para la gente de aquí.--publicaré mi respuesta más adelante.

¿Fue útil?

Solución

Absolutamente, especialmente al tratar con muchas de estas permutaciones/combinaciones, definitivamente puedo ver que la primera pasada sería un problema.

Interesante implementación en Python, aunque escribí una buena en C y Ocaml basada en el "Algoritmo 515" (ver más abajo).Escribió el suyo en Fortran como era común en ese entonces para todos los artículos del "Algoritmo XX", bueno, esa asamblea o c.Tuve que reescribirlo y hacer algunas pequeñas mejoras para trabajar con matrices, no con rangos de números.Este tiene acceso aleatorio, todavía estoy trabajando para obtener algunas implementaciones interesantes de las mencionadas en el fascículo 2 del cuarto volumen de Knuth.Le daré una explicación de cómo funciona esto al lector.Aunque si alguien tiene curiosidad, no me opondría a escribir algo.

/** [combination c n p x]
 * get the [x]th lexicographically ordered set of [p] elements in [n]
 * output is in [c], and should be sizeof(int)*[p] */
void combination(int* c,int n,int p, int x){
    int i,r,k = 0;
    for(i=0;i<p-1;i++){
        c[i] = (i != 0) ? c[i-1] : 0;
        do {
            c[i]++;
            r = choose(n-c[i],p-(i+1));
            k = k + r;
        } while(k < x);
        k = k - r;
    }
    c[p-1] = c[p-2] + x - k;
}

~"Algoritmo 515:Generación de un Vector a partir del Índice Lexicográfico”;Hebillas, B.P. y Lybanon, M.Transacciones ACM sobre software matemático, vol.3, no.2 de junio de 1977.

Otros consejos

Con el nuevo Python 2.6, tienes una solución estándar con el módulo itertools que devuelve el producto cartesiano de iterables:

import itertools

print list(itertools.product([1,2,3], [4,5,6]))
   [(1, 4), (1, 5), (1, 6),
   (2, 4), (2, 5), (2, 6),
   (3, 4), (3, 5), (3, 6)]

Puede proporcionar un argumento de "repetición" para ejecutar el producto con un iterable y él mismo:

print list(itertools.product([1,2], repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
(2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2)]

También puedes modificar algo con combinaciones:

print list(itertools.combinations('123', 2))
[('1', '2'), ('1', '3'), ('2', '3')]

Y si el orden importa, existen permutaciones:

print list(itertools.permutations([1,2,3,4], 2))
[(1, 2), (1, 3), (1, 4),
   (2, 1), (2, 3), (2, 4),
   (3, 1), (3, 2), (3, 4),
   (4, 1), (4, 2), (4, 3)]

Por supuesto, todas esas cosas interesantes no hacen exactamente lo mismo, pero puedes usarlas de una forma u otra para resolver tu problema.

Sólo recuerda que puedes convertir una tupla o una lista en un conjunto y viceversa usando list(), tuple() y set().

¡Interesante pregunta!

Haría esto eligiendo combinaciones, algo como lo siguiente en Python.La parte más difícil es probablemente la verificación del primer paso, es decir, if f(1,2,3) returns true, ¿Es ese un resultado correcto?Una vez que haya verificado esto, esta será una buena base para las pruebas de regresión.

Probablemente sea una buena idea crear un conjunto de casos de prueba que sepa que serán todos verdaderos (p. ej.3,4,5 para este caso triangular) y un conjunto de casos de prueba que sabes que serán todos falsos (p. ej.0,1,inf).Entonces podrás verificar más fácilmente que las pruebas sean correctas.

# xpermutations from http://code.activestate.com/recipes/190465
from xpermutations import *

lengths=[-1,0,1,5,10,0,1000,'inf']
for c in xselections(lengths,3):        # or xuniqueselections
    print c
(-1,-1,-1);
(-1,-1,0);
(-1,-1,1);
(-1,-1,5);
(-1,-1,10);
(-1,-1,0);
(-1,-1,1000);
(-1,-1,inf);
(-1,0,-1);
(-1,0,0);
...

Creo que puedes hacer esto con el Atributo de prueba de fila (disponible en MbUnit y versiones posteriores de NUnit) donde puede especificar varios conjuntos para completar una prueba unitaria.

Si bien es posible crear muchos datos de prueba y ver qué sucede, es más eficiente intentar minimizar los datos que se utilizan.

Desde una perspectiva típica de control de calidad, sería conveniente identificar diferentes clasificaciones de entradas.Produzca un conjunto de valores de entrada para cada clasificación y determine las salidas apropiadas.

Aquí hay una muestra de clases de valores de entrada.

  • triángulos válidos con números pequeños como (1 mil millones, 2, mil millones, 2 mil millones)
  • triángulos válidos con números grandes como (0.000001, 0.00002, 0.00003)
  • triángulos obtusos válidos que son "casi" planos como (10, 10, 19.9999)
  • triángulos agudos válidos que son "casi" planos como (10, 10, 0000001)
  • triángulos no válidos con al menos un valor negativo
  • Triángulos inválidos donde la suma de dos lados es igual al tercero.
  • Triángulos inválidos donde la suma de dos lados es mayor que el tercero.
  • valores de entrada que no son numéricos

...

Una vez que esté satisfecho con la lista de clasificaciones de entrada para esta función, podrá crear los datos de prueba reales.Probablemente sería útil probar todas las permutaciones de cada elemento.(p.ej.(2,3,4), (2,4,3), (3,2,4), (3,4,2), (4,2,3), (4,3,2)) Normalmente, encontrará que hay algunas clasificaciones que se le escaparon (como el concepto de inf como parámetro de entrada).

Los datos aleatorios durante un período de tiempo también pueden ser útiles, ya que pueden encontrar errores extraños en el código, pero generalmente no son productivos.

Lo más probable es que esta función se utilice en algún contexto específico donde se aplican reglas adicionales (p. ej.sólo los valores enteros o los valores deben estar en incrementos de 0,01, etc.) Estos se suman a la lista de clasificaciones de parámetros de entrada.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top