X
BLOG

Hacia la cobertura total de la prueba de regresión

Hacia la cobertura total de la prueba de regresión Tiempo de leer: 3 minutos

Por sorprendente que parezca, incluso completo cobertura de ruta no significa que su código siempre se comporte correctamente.

Si está utilizando un enfoque de desarrollo basado en pruebas (TDD), estará familiarizado con la idea de usar pruebas unitarias como una especie de especificación para el código bajo prueba. Primero escribe una prueba que afirma lo que se supone que debe hacer un nuevo método, observa cómo falla y agrega el código de implementación suficiente para que pase. Si muestra el caso de prueba del Listado 4 a un desarrollador y solicita una implementación, el resultado podría ser un método que siempre devuelve 0, como se muestra en el Listado 5. Curiosamente, el desarrollador ni siquiera violaría el espíritu de TDD al hacerlo. . Habría una cobertura de ruta del 100% y ninguna falla de prueba, pero obviamente la implementación no funcionaría correctamente. En la vida real, este tipo de problemas rara vez aparecen en forma de métodos simples que agregan dos valores, pero generalmente toman una forma más complicada. El problema fundamental es que un conjunto de pruebas unitarias puede proporcionar una cobertura de ruta completa para un método, pero al mismo tiempo puede no proporcionar una especificación completa de ese método. Un escenario típico es que un desarrollador optimiza la implementación de un método existente de tal manera que todos los casos de prueba aún pasan, pero la funcionalidad no confirmada previamente se elimina o cambia inadvertidamente. Esto puede suceder incluso con una cobertura de ruta del 100%.

El ejemplo de código ilustrativo del Listado 2 requeriría 256 casos de prueba diferentes (para todos los valores posibles del byte de tipo) para lograr un total pruebas de regresión cobertura. Sin los casos de prueba adicionales, un desarrollador podría reemplazar la implementación original con código simplificado que devuelva resultados correctos solo para las entradas de prueba 0, 1, 2 y 3, pero simplemente arroja una excepción de operación no admitida para todas las demás entradas. Todos los casos de prueba existentes pasan, pero se pierde una parte de la funcionalidad original. Incluso un conjunto de pruebas unitarias que proporciona una cobertura de ruta completa no está garantizado para detectar tal regresión.

Si la cobertura de la ruta ya es difícil de lograr, la cobertura de regresión completa solo puede considerarse una imposibilidad práctica. El método de suma del Listado 4 toma dos parámetros enteros, cada uno de los cuales puede asumir 232 valores diferentes. La cobertura de regresión completa para este método requeriría 264 (es decir, 232 × 232) casos de prueba. Con un enfoque de prueba parametrizado inteligente, sería posible representar todos estos casos de prueba de una manera compacta, pero sería imposible ejecutar todas las pruebas dentro de un período de tiempo razonable. La cobertura de regresión completa detectaría incluso problemas sutiles como el infame error Pentium FDIV; desafortunadamente, es completamente impráctico a todos los efectos.

No garantizar el correcto funcionamiento de algo tan simple como un método de adición no es precisamente inspirador de confianza. Entonces, a excepción de crear casos de prueba que ejerciten todas las combinaciones posibles de entradas, ¿qué puede hacer en la práctica para lograr un nivel razonable de protección contra fallas de regresión? Claramente, cuantas más entradas diferentes siga disparando en un método probado, mejor será su cobertura de regresión. La pregunta es qué entradas elegir para sus casos de prueba. Los valores extremos (o los llamados "casos de esquina") son una buena opción. Las entradas de prueba para un parámetro int podrían, por ejemplo, usar Integer.MAX_VALUE, Integer.MAX_VALUE-1, 1, 0, -1, Integer.MIN_VALUE + 1 e Integer.MIN_VALUE como entradas de prueba. De manera similar, una referencia nula, una cadena vacía y varias cadenas que contienen caracteres especiales son buenas entradas de prueba para un parámetro de cadena.

Los casos de prueba que tienen como objetivo mejorar la cobertura de regresión a menudo tienen una estructura de prueba común, pero utilizan diferentes valores de entrada. En estas situaciones, puede ser útil utilizar herramientas que admitan la parametrización de casos de prueba, que extrae la estructura de prueba común y separa los datos de prueba en una hoja de cálculo de Excel o en algún otro almacén de datos externo. Otra opción para mejorar la cobertura de regresión de un conjunto de pruebas es la llamada prueba de perturbación, que aplica modificaciones menores (como sumar o restar un número pequeño) a los valores de entrada de las pruebas existentes con el objetivo de exponer nuevas rutas de código interesantes y afirmar previamente comportamiento no afirmado. Los valores de casos de esquina y las pruebas de perturbación son heurísticos en lugar de sistemáticos, pero ambos pueden aumentar la cobertura de regresión y se pueden aplicar manualmente o mediante herramientas automatizadas como Parasoft Jtest.

La Tabla 1 proporciona un resumen de los casos de prueba que son necesarios para lograr el 100% de cobertura de declaración, rama, ruta y regresión completa para el método probado del Listado 2.


Tabla 1: Pruebe las entradas para lograr una cobertura del 100% del Listado 2

Escrito por

Parasoft

Las herramientas de prueba de software automatizadas líderes en la industria de Parasoft respaldan todo el proceso de desarrollo de software, desde que el desarrollador escribe la primera línea de código hasta las pruebas unitarias y funcionales, hasta las pruebas de rendimiento y seguridad, aprovechando los entornos de prueba simulados en el camino.

Reciba las últimas noticias y recursos sobre pruebas de software en su bandeja de entrada.

Prueba Parasoft