unit testing - unitaria - Cómo usar combinaciones de conjuntos como datos de prueba
pruebas unitarias c# (5)
Absolutamente, especialmente lidiando con muchas de estas permutaciones / combinaciones definitivamente puedo ver que el primer pase sería un problema.
Implementación interesante en Python, aunque escribí uno bueno en C y Ocaml basado 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 y no con rangos de números. Este tiene acceso aleatorio, todavía estoy trabajando para 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;
}
~ "Algoritmo 515: Generación de un vector del índice lexicográfico"; Buckles, BP y Lybanon, M. ACM Transactions on Mathematical Software, vol. 3, No. 2, junio de 1977.
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
cada vez que se le dan 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 .; Ademá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: ¡En verdad conozco la respuesta a esto, pero podría ser útil para otros y un desafío para la gente aquí! - Publicaré mi respuesta más tarde.
Creo que puede hacer esto con el atributo de prueba de fila (disponible en MbUnit y versiones posteriores de NUnit) donde puede especificar varios conjuntos para rellenar una prueba de unidad.
Si bien es posible crear muchos datos de prueba y ver qué sucede, es más eficiente intentar minimizar los datos que se usan.
Desde una perspectiva de control de calidad típica, le conviene 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 billón, 2, billón, 2 billones)
- 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 inválidos con al menos un valor negativo
- triángulos inválidos donde la suma de dos lados es igual a la tercera
- triángulos inválidos donde la suma de dos lados es mayor que la tercera
- valores de entrada que no son numéricos
...
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, solo valores enteros o valores deben estar en incrementos de 0,01, etc.). Estos se agregan a la lista de clasificaciones de los parámetros de entrada.
¡Interesante pregunta!
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 ese un resultado correcto? Una vez que haya verificado eso, esta es 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 verdaderos (p. Ej., 3,4,5 para este caso triangular) y un conjunto de casos de prueba que sepa que serán todos falsos (p. Ej., 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); ...
Con el nuevo Python 2.6, tiene una solución estándar con el módulo itertools que devuelve el producto cartesiano de los 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 realizar el producto con un iterable y sí 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 puede modificar algo con combinaciones:
print list(itertools.combinations(''123'', 2))
[(''1'', ''2''), (''1'', ''3''), (''2'', ''3'')]
Y si el orden es importante, hay 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.
Solo recuerde que puede convertir una tupla o una lista en un conjunto y viceversa usando list (), tuple () y set ().