2008-08-02 18 views
18

Me gustaría probar una función con una tupla de un conjunto de mayúsculas y valores normales. Por ejemplo, al probar una función que devuelve true siempre que se le den tres longitudes que forman un triángulo válido, tendría casos específicos, números negativos/pequeños/grandes, valores próximos a desbordarse, etc .; lo que 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.Cómo utilizar combinaciones de conjuntos como datos de prueba

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

Como nota: En realidad sé la respuesta a esto, pero podría ser de utilidad para otros, y un reto para la gente de aquí! - Publicaré mi respuesta más tarde.

+0

[Abacus github] (https://github.com/foo123/Abacus) una biblioteca de combinatorics para Node.JS, Python, PHP, Actionscript (ps soy el autor) –

Respuesta

14

Absolutamente, especialmente los destinados a un montón de estas permutaciones/combinaciones Definitivamente puedo ver que el primer paso sería un problema.

Implementación interesante en python, aunque escribí una buena en C y Ocaml basada en "Algorithm 515" (ver abajo). Escribió el suyo en Fortran ya que era común en aquel entonces para todos los documentos del "Algoritmo XX", bueno, esa asamblea o c. Tuve que volver a escribirlo y hacer algunas pequeñas mejoras para trabajar con matrices, no con rangos de números. Éste tiene acceso aleatorio, todavía estoy trabajando en obtener algunas implementaciones agradables de las mencionadas en el fascículo 2 del 4to volumen de Knuth. Explicaré cómo funciona esto para el 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; 
} 

~ "Algorithm 515: Generation of a Vector from the Lexicographical Index"; Buckles, B. P. y Lybanon, M. ACM Transactions on Mathematical Software, vol. 3, No. 2, junio de 1977.

+0

¿Qué 'elija()' hacer ? ¿Eso básicamente devuelve 'n-c [i]' elige 'p- (i + 1) 1'? – mkb

+0

@mkb Por supuesto. – nlucaroni

+0

Lo siento, no sigo el comportamiento elegido. Parece que se define como auto reflexivo; elije si elige. ¿Podría decirme qué hace en términos más simples? – CuppM

4

¡Pregunta interesante!

Haría esto seleccionando 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 un resultado correcto? Una vez que haya verificado eso, esta es una buena base para las pruebas de regresión.

Probablemente es una buena idea hacer un conjunto de casos de prueba que sepa que serán verdaderos (por ejemplo, 3,4,5 para este caso triangular), y un conjunto de casos de prueba que usted sabe que serán todos falsos (por ejemplo, 0,1, inf). Entonces puede verificar más fácilmente que las pruebas son 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); 
... 
2

Creo que puede hacer esto con el Row Test Attribute (disponible en MbUnit y versiones posteriores de NUnit) donde puede especificar varios conjuntos para rellenar una prueba unitaria.

0

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 de control de calidad típico, querrá identificar diferentes clasificaciones de entradas. Produzca un conjunto de valores de entrada para cada clasificación y determine las salidas apropiadas.

He aquí una muestra de clases de valores de entrada

  • triángulos válidos con números pequeños, tales como (1 mil millones, 2, mil millones, 2 mil millones)
  • triángulos válidos con grandes números, tales como (0,000001, 0,00002 , 0.00003)
  • triángulos obtusos válidos que sean 'almost'flat tales como (10, 10, 19.9999)
  • triángulos agudos válidas que son 'casi' plana tal como (10, 10, 0000001)
  • triángulos no válidos Wisconsin º al menos un valor negativo
  • triángulos no válidos, donde la suma de dos lados es igual a la tercera
  • triángulos no válidos donde la suma de dos partes es mayor que el tercer
  • valores de entrada que son no numérico

...

Una vez que esté satisfecho con la lista de clasificaciones de entrada para esta función, puede crear los datos de prueba reales. Probablemente, sería útil probar todas las permutaciones de cada elemento. (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 omitió (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.

Es más probable que esta función se utilice en un contexto específico donde se aplican reglas adicionales (por ejemplo, valores enteros o valores en incrementos de 0,01, etc.). Estas se agregan a la lista de parámetros de entrada.

4

Con el nuevo Python 2.6, que tienen 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)] 

le puede proporcionar una "repetición" argumento para llevar a cabo el producto con un iterable y sí:

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 puede ajustar algo con combinaciones así:

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

Y si el orden es importante, no son 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, todo lo que se enfríe la materia no es exactamente lo mismo, pero se puede utilizar de una manera u otra para que resolver el problema.

Recuerde que puede convertir una tupla o una lista en un conjunto y viceversa usando list(), tuple() y set().

Cuestiones relacionadas