Tengo una clase que encapsula los resultados de una medición científica. Estoy construyendo pruebas unitarias desde el principio, pero no tengo mucha experiencia con las pruebas unitarias y no estoy seguro de qué comportamientos debería probar y cómo.
Mi clase hace tres tipos de cosas:
- Lee datos de medición de un archivo (o una cadena) en sus variables de instancia
- Escribe sus datos de medición en un archivo o una cadena
- Realiza cálculos sobre sus datos (por ejemplo, obtener el promedio de un conjunto de números)
Mi enfoque en este momento es incluir un archivo de datos de ejemplo bien conocido en mi test
directorio. Una prueba lee los datos del archivo, los pasa a mi clase y se asegura de que cumplan con algunos controles básicos de cordura. Otra prueba pasa el nombre del archivo a mi clase, deja que la clase lo lea y ejecuta las mismas pruebas. El resto de las pruebas leen los datos del archivo, los pasan a mi clase y verifican que los resultados de los métodos de procesamiento de datos sean correctos, dado lo que sé sobre ese conjunto de datos.
Sin embargo, esto parece bastante enredado. Las pruebas que verifican (3) suponen implícitamente que los comportamientos de (1) son correctos, ya que son las funciones en (1) las que se utilizan para llenar la clase en primer lugar. Y las pruebas de (1) podrían beneficiarse de las extensas comprobaciones realizadas por las pruebas de (3). ¿Estoy estructurando mal mis pruebas unitarias, o es solo un resultado natural del hecho de que necesito usar un conjunto de datos específico en mis pruebas?
fuente
Respuestas:
Lo que está haciendo son pruebas de integración, porque como probablemente pueda ver, sus pruebas dependen de otras partes de su código. Esto está bien, pero es bueno saber cuándo estás mirando artículos / ejemplos / etc. en línea.
Algunos puntos a considerar y cosas para recordar:
editar> Esto ya ha sido aceptado, pero quería agregar algo que aprendí hace mucho tiempo a través de Pragmatic Unit Testing :
Prueba de unidad con su BICEP correcto
fuente
Creo que su clase es difícil de evaluar porque tiene demasiadas responsabilidades. Los mencionas tú mismo
Idealmente, una clase debería tener una sola responsabilidad o un área de responsabilidad única. En este caso, definitivamente debe tener una clase que contenga solo la lógica para realizar los cálculos.
Si tuviera eso, tal vez podría tener una función como esta:
Esto se vuelve relativamente fácil de probar, ya que puede proporcionar fácilmente una serie de mediciones bien definidas en una prueba.
Supongo que aquí lees del archivo una vez para obtener todas las medidas a la vez. Si recopila nuevas medidas escritas en el archivo a lo largo del tiempo, su clase podría verse así:
Todavía es fácil de probar, porque puede alimentar a la clase con una serie de mediciones bien definidas durante la prueba y leer el resultado, sin tener que depender del sistema de archivos.
Una clase diferente podría tener la responsabilidad de leer los datos de Medición del archivo. Esto podría dividirse nuevamente en leer datos de un archivo y analizar los datos como objetos de medición, para permitir probar la lógica de análisis por separado sin depender del sistema de archivos, etc.
Si es difícil escribir una prueba de unidad, esto a menudo es una señal de que su "unidad" tiene múltiples responsabilidades, demasiadas dependencias o, de otras formas, no es SÓLIDA .
fuente
Las pruebas unitarias deben probar dos conjuntos de casos:
Los casos muy básicos: es el cálculo correcto, suman los totales, etc. Utilice datos simples y fáciles de verificar para estos casos.
The edge cases: fecha de entrega del 29 de febrero de 2016, cantidad de pedido de 999,999, artículos con un precio de $ 0.00, GPS para el Polo Norte (¡trate de mudarse al oeste!), Etc., etc.
fuente
Creo que muchas de las respuestas son acertadas, en el sentido de que muchas de las pruebas esenciales parecen estar combinadas en una instancia de prueba unitaria. PERO.
Muchas funciones requieren datos complicados y producen resultados complicados. El procesamiento de imágenes, por ejemplo, puede tener una función compacta que produce una máscara a partir de una imagen. Un controlador de prueba (yo diría que es apropiado) leería una imagen, la procesaría, escribiría un archivo de imagen y compararía el archivo resultante con un archivo de imagen de referencia.
Probar la integración en el objetivo de toda esa funcionalidad sería una prueba de integración. Probar una sola función de su objetivo, una entrada complicada a una salida complicada, es una prueba unitaria adecuada.
fuente