Las pruebas aleatorias son una técnica de prueba de software de caja negra en la que los programas se prueban generando entradas aleatorias e independientes. Los resultados se comparan con las especificaciones del software para verificar si la prueba es exitosa o no. [ 1 ] En ausencia de especificaciones, se utilizan las excepciones del lenguaje, lo que significa que si surge una excepción durante la ejecución de la prueba, significa que hay una falla en el programa. También se utiliza para evitar pruebas sesgadas.
Historial de pruebas aleatorias
Las pruebas aleatorias de hardware fueron examinadas por primera vez por Melvin Breuer en 1971 y el esfuerzo inicial para evaluar su efectividad fue realizado por Pratima y Vishwani Agrawal en 1975. [ 2 ]
En el ámbito del software, Duran y Ntafos habían examinado las pruebas aleatorias en 1984. [ 3 ]
Howden describió el uso de pruebas de hipótesis como base teórica para pruebas aleatorias en su libro Functional Testing and Analysis . El libro también incluía el desarrollo de una fórmula simple para estimar el número de pruebas n necesarias para tener una confianza de al menos 1-1/ n en una tasa de fallos no mayor que 1/n. La fórmula es el límite inferior n log n , que indica el gran número de pruebas sin fallos necesarias para tener incluso una confianza moderada en un límite de tasa de fallos moderado. [ 4 ]
Descripción general
Considere la siguiente función de C++:
int myAbs ( int x ) { if ( x > 0 ) { return x ; } else { return x ; // error: debería ser '-x' } }Ahora bien, las pruebas aleatorias para esta función podrían ser {123, 36, -35, 48, 0}. Solo el valor '-35' activa el error. Si no hay una implementación de referencia para verificar el resultado, el error aún podría pasar desapercibido. Sin embargo, se podría agregar una aserción para verificar los resultados, como:
void testAbs ( int n ) { for ( int i = 0 ; i < n ; i ++ ) { int x = getRandomInput (); int result = myAbs ( x ); assert ( result >= 0 ); } }En ocasiones, se dispone de la implementación de referencia, por ejemplo, al implementar un algoritmo sencillo de una forma mucho más compleja para obtener un mejor rendimiento. Por ejemplo, para probar una implementación del algoritmo de Schönhage-Strassen , se puede utilizar la operación estándar "*" sobre números enteros:
int getRandomInput () { // … }void testFastMultiplication ( int n ) { for ( int i = 0 ; i < n ; i ++ ) { long x = getRandomInput (); long y = getRandomInput (); long result = fastMultiplication ( x , y ); assert ( x * y == result ); } }Si bien este ejemplo se limita a tipos simples (para los cuales se puede usar un generador aleatorio simple), las herramientas dirigidas a lenguajes orientados a objetos suelen explorar el programa para probar y encontrar generadores (constructores o métodos que devuelven objetos de ese tipo) y llamarlos usando entradas aleatorias (ya sea generadas de la misma manera o generadas usando un generador pseudoaleatorio si es posible). Estos enfoques mantienen un conjunto de objetos generados aleatoriamente y usan una probabilidad para reutilizar un objeto generado o crear uno nuevo. [ 5 ]
Sobre el azar
Según el artículo fundamental sobre pruebas aleatorias de D. Hamlet
[...] el significado técnico y matemático de "pruebas aleatorias" se refiere a una falta explícita de "sistema" en la selección de los datos de prueba, de modo que no existe correlación entre las diferentes pruebas. [ 1 ]
Fortalezas y debilidades
Las pruebas aleatorias son elogiadas por las siguientes ventajas:
- Su uso es económico: no necesita ser muy preciso con respecto al programa que se está probando.
- No tiene ningún sesgo: a diferencia de las pruebas manuales, no pasa por alto errores debido a una confianza mal depositada en algún código.
- Es rápido encontrar posibles fallos: normalmente, una sesión de pruebas solo lleva un par de minutos.
- Si el software está correctamente configurado, detecta errores reales.
Se han descrito las siguientes debilidades :
- Solo detecta errores básicos (por ejemplo, la desreferenciación de punteros nulos ).
- Su precisión depende de las especificaciones, y las especificaciones suelen ser imprecisas.
- Se compara negativamente con otras técnicas para encontrar errores (por ejemplo, el análisis estático de programas ).
- Si se seleccionan entradas diferentes al azar en cada ejecución de prueba, esto puede crear problemas para la integración continua porque las mismas pruebas pasarán o fallarán al azar. [ 6 ]
- Algunos argumentan que sería mejor cubrir cuidadosamente todos los casos relevantes con pruebas construidas manualmente de forma transparente, en lugar de confiar en la aleatoriedad. [ 6 ]
- Puede requerir un número muy elevado de pruebas para niveles de confianza moderados en tasas de fallo moderadas. Por ejemplo, se necesitarán 459 pruebas sin fallos para tener al menos un 99 % de confianza en que la probabilidad de fallo sea inferior a 1/100. [ 4 ]
Tipos de pruebas aleatorias
Con respecto a la entrada
- Generación de secuencias de entrada aleatorias (es decir, una secuencia de llamadas a métodos)
- Secuencia aleatoria de entradas de datos (a veces llamada prueba estocástica), por ejemplo, una secuencia aleatoria de llamadas a métodos.
- Selección aleatoria de datos de una base de datos existente.
Guiado vs. no guiado
Implementaciones
Algunas herramientas que implementan pruebas aleatorias:
- QuickCheck es una conocida herramienta de prueba, desarrollada originalmente para Haskell pero adaptada a muchos otros lenguajes, que genera secuencias aleatorias de llamadas a la API basadas en un modelo y verifica las propiedades del sistema que deberían cumplirse después de cada ejecución.
- Randoop: genera secuencias de métodos e invocaciones de constructores para las clases bajo prueba y crea pruebas JUnit a partir de estas.
- Simulant: una herramienta de Clojure que ejecuta simulaciones de varios agentes (por ejemplo, usuarios con diferentes perfiles de comportamiento) basándose en un modelo estadístico de su comportamiento, registrando todas las acciones y resultados en una base de datos para su posterior exploración y verificación.
- AutoTest: una herramienta integrada a EiffelStudio que prueba automáticamente el código Eiffel con contratos basados en el prototipo de investigación homónimo. [ 5 ] ·
- York Extensible Testing Infrastructure (YETI): una herramienta independiente del lenguaje que admite varios lenguajes de programación (Java, JML, CoFoJa, .NET, C, Kermeta).
- GramTest es una herramienta de prueba aleatoria basada en gramática, escrita en Java, que utiliza la notación BNF para especificar las gramáticas de entrada.
Crítica
Las pruebas aleatorias tienen en la práctica un nicho especializado, principalmente porque rara vez se dispone de un oráculo eficaz, pero también debido a las dificultades con el perfil operativo y con la generación de valores de entrada pseudoaleatorios. [ 1 ]
Un oráculo de prueba es un instrumento para verificar si los resultados coinciden con las especificaciones del programa. Un perfil de operación es información sobre los patrones de uso del programa y, por lo tanto, sobre qué partes son más importantes.
Para los lenguajes de programación y plataformas que tienen contratos (por ejemplo, Eiffel, .NET o varias extensiones de Java como JML, CoFoJa...), los contratos actúan como oráculos naturales y el enfoque se ha aplicado con éxito. [ 5 ] En particular, las pruebas aleatorias encuentran más errores que las inspecciones manuales o los informes de los usuarios (aunque diferentes). [ 9 ]
Véase también
- Pruebas de fuzzing : un tipo de prueba aleatoria que proporciona entradas no válidas al programa que se está probando.
- Pruebas unitarias sistemáticas perezosas#Pruebas sistemáticas : una forma sistemática de explorar "todas" las llamadas a métodos, como la implementada, por ejemplo, por Java Path Finder de la NASA (que combina pruebas con verificación de modelos al limitar el espacio de estados a un tamaño razonable por diversos medios).
- Generación aleatoria restringida en SystemVerilog
- Caso excepcional
- Caso límite
- Pruebas de concólico
Referencias
- 1 2 3 Richard Hamlet (1994). «Pruebas aleatorias». En John J. Marciniak (ed.). Enciclopedia de ingeniería de software (1.ª ed.). John Wiley and Sons. ISBN 978-0471540021.
- ↑ Agrawal, P.; Agrawal, VD (1 de julio de 1975). "Análisis probabilístico del método de generación de pruebas aleatorias para redes lógicas combinacionales irredundantes". IEEE Transactions on Computers . C-24 (7): 691– 695. doi : 10.1109/TC.1975.224289 .
- ↑ Duran, JW; Ntafos, SC (1 de julio de 1984). "Una evaluación de las pruebas aleatorias". IEEE Transactions on Software Engineering . SE-10 (4): 438– 444. doi : 10.1109/TSE.1984.5010257 .
- 1 2 Howden, William (1987). Pruebas y análisis de programas funcionales . Nueva York: McGraw Hill. págs. 51–53 . ISBN 0-07-030550-1.
- 1 2 3 "AutoTest - Cátedra de Ingeniería de Software" . se.inf.ethz.ch. Consultado el 15 de noviembre de 2017 .
- 1 2 "¿Es una mala práctica generar datos de prueba aleatoriamente?" . stackoverflow.com . Consultado el 15 de noviembre de 2017 .
- ↑ Pacheco, Carlos; Shuvendu K. Lahiri; Michael D. Ernst; Thomas Ball (mayo de 2007). «Generación de pruebas aleatorias dirigidas por retroalimentación» (PDF) . 29.ª Conferencia Internacional sobre Ingeniería de Software (ICSE'07) . págs. 75–84 . doi : 10.1109/ICSE.2007.37 . ISBN 978-0-7695-2828-1ISSN 0270-5257
- ↑ TY Chen; F.-C. Kuo; RG Merkel; TH Tse (2010), "Pruebas aleatorias adaptativas: El ARTE de la diversidad de casos de prueba" , Journal of Systems and Software , 83 (1): 60–66 , doi : 10.1016/j.jss.2009.02.022 , hdl : 10722/89054
- ↑ Ilinca Ciupa; Alexander Pretschner; Manuel Oriol; Andreas Leitner; Bertrand Meyer (2009). "Sobre el número y la naturaleza de las fallas encontradas mediante pruebas aleatorias". Software Testing, Verification and Reliability . 21 : 3–28 . doi : 10.1002/stvr.415 .
Enlaces externos
- Pruebas aleatorias de Andrea Arcuri.
- Pruebas aleatorias realizadas por Richard Hamlet, profesor emérito de la Universidad Estatal de Portland; una valiosa lista de recursos al final del artículo.
- Wiki sobre pruebas aleatorias en Cunningham & Cunningham, Inc.
- Pruebas de software