Pruebas parametrizadas: ¿cuándo y por qué las usa?

15

Recientemente en el trabajo hemos tenido algunas diferencias de opinión con respecto a las pruebas parametrizadas . Normalmente usamos un estilo TDD (o al menos lo intentamos), así que entiendo los beneficios de ese enfoque. Sin embargo, estoy luchando por ver la ganancia que traen las pruebas parametrizadas. Como referencia, trabajamos en un servicio y sus bibliotecas que están expuestas a través de una interfaz RESTful.

Lo que he visto hasta ahora son pruebas que son, al menos usando JUnit dentro de Eclipse:

  • Falta de detalles: cuando una prueba falla, es muy difícil ver los parámetros que la hicieron fallar
  • A menudo complicado de crear
  • Tienden a crearse después de que el código ha sido escrito, estrictamente no es un inconveniente como tal, pero ¿las personas se preparan teniendo en cuenta las pruebas parametrizadas cuando comienzan un fragmento de código?

Si alguien tiene ejemplos de dónde son realmente útiles o incluso alguna buena pista para usarlos, sería fantástico. Quiero asegurarme de que no solo soy obstinado porque personalmente no elijo usarlos y ver si son algo que deberíamos considerar ser parte de nuestro arsenal de pruebas.

neilprosser
fuente
1
El problema no es con la idea sino con la biblioteca torpe. En C # la sintaxis es mucho más amigable, cuando usas decir MbUnit. Si, es una buena idea. Agregue su propio código para facilitar este proceso - lea cosas de los archivos - lo que sea que funcione. Observe también cómo MsTest maneja esto.
Trabajo
Nosotros (Square) escribimos Burst para abordar algunos de estos problemas Parameterized. Generalmente agrega menos repetitivo, y deja bastante claro dónde falló una prueba.
Daniel Lubarov

Respuestas:

4

El problema con probar cualquier pieza de software es que la complejidad explota bastante rápido. El hecho es que no puede probar todas las combinaciones posibles de parámetros pasados ​​a sus métodos. Phadke aboga por un enfoque de diseño de experimentos (DOE), que permite la generación de la lista probable de valores de parámetros que deben probarse.

La idea es que, aunque no realice pruebas exhaustivas, la mayoría de los defectos provocan una "región de falla" en lugar de una falla de punto aislada. El enfoque del DOE Phadke aboga por el uso de arreglos ortogonales que muestren el espacio de parámetros con la suficiente precisión como para golpear todas las regiones de fallas posibles.

Las fallas aisladas probablemente no se identificarán, pero generalmente son menos que las regiones de fallas.

El enfoque DOE le brinda una forma sistemática de elegir los valores de los parámetros para variar.

Peter K.
fuente
El enlace proporcionado está roto.
Josh Gust
1
@JoshGust Se soluciona fácilmente con Google. Gracias por el aviso.
Peter K.
4

Pueden ser útiles para garantizar que su código maneje no solo la ruta feliz, sino también los casos extremos. Después de saber que su código funciona con variables normales, parametrice el caso de prueba y asegúrese de que nulos y ceros, cadenas vacías, números grandes, cadenas largas, caracteres Unicode extraños, etc., también funcionen bien.

Ethel Evans
fuente
2

Hay al menos dos tipos de pruebas parametrizadas, al menos en JUnit 4.8. Esos son: Pruebas parametrizadas ( @RunWith(Parameterized.class)) que requieren una fuente de datos, que genera / lee configuraciones de parámetros predefinidas, y Teorías ( @RunWith(Theories.class)) que, dado uno o más conjuntos de entradas posibles por tipo de argumento, pueden ejercer la especificación de métodos dados. Se parece más a menos así:

  • especifique algunos valores posibles ( @DataPoints) para argumentos de cadena (como nullcadena vacía, cadena no vacía, cadena realmente larga)
  • especifique algunos valores posibles ( @DataPoints) para los argumentos de la clase Animal (como null, Doginstancia, Catinstancia, Birdinstancia)
  • prepare @Theoryque acepta un Stringparámetro y un Animalparámetro. se ejecutará con todas las combinaciones posibles de los valores de parámetros posibles (en un ejemplo dado, sería 4x4 = 16 combinaciones, incluyendo ( null, null))
  • si el método bajo prueba no puede aceptar alguna combinación, use Assume.assumeThatimportaciones estáticas para filtrar combinaciones no válidas (por ejemplo, cuando desee verificar el comportamiento del método para cadenas no vacías, una de las primeras líneas sería "suponga que no es nulo"

Como se escribió anteriormente, no tiene sentido probar todas las combinaciones posibles de cada método (explota los conjuntos de prueba, imagine probar un método con 5 parámetros, cada uno con solo 5 valores posibles: 5 ** 5 -> más de 3000 ejecuciones de prueba !), pero para los métodos de misión crítica (como los métodos API) lo alentaría, solo para estar seguro ...

Adam Hepner
fuente
1

Ejemplo genérico

  • Métodos con argumentos de cadena. Use pruebas parametrizadas para probar diferentes entradas y sus salidas esperadas. Es mucho más práctico tener una lista de pares (entrada, esperada) que escribir un TC para cada par.

  • Aplicar el mismo escenario en diferentes argumentos. Tenemos un escenario que funciona con el Animalobjeto y tenemos muchas subclases comoDog , Cat, Bird. Crea una lista de los animales disponibles y prueba el escenario en ellos.

Hormigón para servicio web:

  • Del ejemplo de argumentos de cadena arriba. Pruebe lo que sucede con diferentes argumentos del mismo tipo pero con diferentes valores.
Victor Hurdugaci
fuente
0

Las pruebas parametrizadas funcionan bien para probar funciones / características que tienen una entrada simple cuando desea probar una variedad de entradas.

No funcionan bien para probar diferentes funcionalidades y entradas complejas. No deben usarse como una estructura conveniente para escribir menos código.

Cirem
fuente
1
¿Por qué no deberían usarse los parámetros como una conveniencia para escribir menos código? No hay una gran virtud en proporcionar una lista exhaustiva de un conjunto grande (ish) de casos de prueba.
Jonathan Eunice
1
¿Cómo proporciona su respuesta más información que las otras 5 respuestas?
Adam Zuckerman
-2

Un caso en el que utilizo muchas pruebas parametrizadas de forma TDD es escribir analizadores: puedo comenzar con una lista de entrada y salida esperada y luego escribir el código para que pase todos los casos de prueba.

Pero he visto algunos horrores de las pruebas parametrizadas. No, Virginia, tu conjunto de pruebas no debería necesitar sus propias pruebas unitarias.

Wyatt Barnett
fuente
1
Idealmente, las pruebas parametizadas deben tener la forma "el elemento (n) en la salida real coincide con el elemento (n) en la salida esperada" o similar, y en ese caso no se necesitan pruebas. Pero para cualquier cosa más compleja, preferiría ver una prueba parametizada limpia o dos con sus propios casos de prueba que el habitual "mi (prueba) código es obviamente correcto". Si eso fuera cierto, no escribirías casos de prueba. Obviamente, es posible exagerar con la complejidad y no estoy argumentando que no hay línea, pero creo que hay casos en los que las pruebas de prueba son una buena idea.