¿Es mejor tener un
- Conjunto de pruebas deterministas, que da como resultado que las mismas pruebas tengan éxito
- Conjunto de pruebas no deterministas, que posiblemente cubre más casos
?
Ejemplo: escribe un conjunto de pruebas para probar la funcionalidad del controlador en una aplicación MVC. El controlador requiere datos de la aplicación de una base de datos como entrada durante la prueba. Hay dos opciones para hacer esto:
- Usted codifica qué fila (s) de la base de datos de prueba se seleccionan como entrada (por ejemplo, la fila 10 y 412)
- Utiliza un generador de números aleatorios para elegir pseudoaleatoriamente los datos de la base de datos (dos filas seleccionadas por un generador de números aleatorios)
El primero es determinista: cada ejecución de la prueba para la misma revisión de código debería producir el mismo resultado. El segundo no es determinista: cada ejecución del conjunto de pruebas tiene la posibilidad de producir un resultado diferente. Sin embargo, los datos elegidos al azar podrían ser una mejor representación de los casos límite de datos. ¿Podría simular a un usuario que alimenta mejor a nuestros controladores con datos impredecibles?
¿Cuáles son las razones para elegir uno sobre el otro?
Respuestas:
Cuando cada ejecución de la suite de prueba le da la posibilidad de obtener un resultado diferente, la prueba es casi completamente inútil: cuando la suite muestra un error, tiene una alta probabilidad de que no pueda reproducirlo, y cuando intenta corregir el problema error, no puede verificar si su solución funciona.
Entonces, cuando crea que necesita usar algún tipo de generador de números aleatorios para generar sus datos de prueba, asegúrese de inicializar siempre el generador con la misma semilla, o conserve sus datos de prueba aleatorios en un archivo antes de ingresarlos en su prueba, para que pueda volver a ejecutar la prueba nuevamente con exactamente los mismos datos de la ejecución anterior. De esta manera, puede transformar cualquier prueba no determinista en una prueba determinista.
EDITAR: Usar un generador de números aleatorios para elegir algunos datos de prueba es, en mi humilde opinión, una señal de ser demasiado flojo para elegir buenos datos de prueba. En lugar de arrojar 100,000 valores de prueba elegidos al azar y esperar que esto sea suficiente para descubrir todos los errores serios por casualidad, mejor usa tu cerebro, elige entre 10 y 20 casos "interesantes" y úsalos para el conjunto de pruebas. Esto no solo dará como resultado una mejor calidad de sus pruebas, sino también un rendimiento mucho mayor de la suite.
fuente
Tanto los deterministas como los no deterministas tienen un lugar
Los dividiría de la siguiente manera:
Pruebas unitarias.
Estos deben tener pruebas deterministas y repetibles con los mismos datos exactos cada vez. Las pruebas unitarias acompañan secciones específicas de código aisladas y deben probarlas de manera determinista.
Pruebas de estrés funcional y de entrada.
Estos pueden usar el enfoque no determinista con las siguientes advertencias:
fuente
Ambos.
Las pruebas deterministas y no deterministas tienen diferentes casos de uso y diferentes valores para su suite. En general, las no deterministas no pueden proporcionar la misma precisión que las pruebas deterministas, que lentamente se han convertido en "las pruebas no deterministas no aportan ningún valor". Esto es falso Pueden ser menos precisos, pero también pueden ser mucho más amplios, lo que tiene sus propios beneficios.
Tomemos un ejemplo: escribe una función que ordena una lista de enteros. ¿Cuáles serían algunas de las pruebas unitarias deterministas que encontrarías útiles?
NaN
,INT_MIN
yINT_MAX
¡Y eso es solo una función de clasificación! Claro, podría argumentar que algunos de estos son innecesarios, o que algunos de estos pueden descartarse con un razonamiento informal. Pero somos ingenieros y hemos visto explotar el razonamiento informal en nuestra cara. Sabemos que no somos lo suficientemente inteligentes como para comprender completamente los sistemas que hemos construido o mantener la complejidad en nuestras cabezas. Es por eso que escribimos pruebas en primer lugar. Agregar pruebas no deterministas solo dice que no necesariamente debemos ser lo suficientemente inteligentes como para conocer todas las buenas pruebas a priori. Al incluir datos semialeatorios en su función, es mucho más probable que encuentre un caso límite que se haya perdido.
Por supuesto, eso tampoco descarta las pruebas deterministas. Las pruebas no deterministas ayudan a encontrar errores en grandes extensiones del programa. Sin embargo, una vez que haya encontrado los errores, necesita una forma reproducible de mostrar que lo solucionó. Entonces:
Tenga en cuenta que esto significa que muchos consejos sólidos sobre las pruebas unitarias no se aplican necesariamente a las pruebas no deterministas. Por ejemplo, que deben ser rápidos. Las pruebas de propiedad de bajo nivel deben ser rápidas, pero una prueba no determinista como "simular un usuario haciendo clic al azar en los botones de su sitio web y asegurarse de que nunca obtenga un error 500" debería favorecer la exhaustividad sobre la velocidad. Simplemente haga que una prueba como esa se ejecute independientemente de su proceso de compilación para que no ralentice el desarrollo. Por ejemplo, ejecútelo en su propio cuadro de ensayo privado.
fuente
Realmente no quieres determinista versus no determinista.
Lo que puede desear es "siempre lo mismo" frente a "no siempre lo mismo".
Por ejemplo, puede tener un número de compilación que aumenta con cada compilación, y cuando desea algunos números aleatorios, inicializa un generador de números aleatorios con el número de compilación como semilla. Entonces, en cada compilación, haces tus pruebas con diferentes valores, dándote más oportunidades de encontrar errores.
Pero una vez que se encuentra un error, todo lo que necesita hacer es ejecutar la prueba con el mismo número de compilación, y es reproducible.
fuente