Testing basado en sintaxis: Gramáticas a partir de programas

Slides:



Advertisements
Presentaciones similares
Las tres primeras fases de un compilador suelen agrupan en un sola fase llamada Análisis del programa a compilar y las tres ultimas en una sola fase llamada.
Advertisements

Unidad 1: Conceptos fundamentales Instituto Tecnológico de Toluca Ing. Sistemas Computacionales Asignatura: Programación Lógica y Funcional Presentan Nieto.
Programación II Sesión 3. TABLA DE CONTENIDO  Tipos de Datos en C  Delimitadores  Tipo Char  Tipo Int  Tipo Float  Tipo Double  Constantes  Operadores.
PROGRAMACIÓN ORIENTADA A OBJETOS SEGUNDA UNIDAD: “CLASES, OBJETOS Y MÉTODOS” IRVING YAIR SALAS CHÁVEZ ING. EN SISTEMAS COMPUTACIONALES - ITSLP.
Pruebas de Funcionalidad de Software: Caja Negra y Caja Blanca Curso: Diseño de Sistemas 9no. Semestre.
Funciones en lenguaje C 2 Funciones Definición: – Las funciones son los bloques de construcción básicos de C. Dentro de ellas se da toda la actividad.
Diseño por Contrato Tecnología de Objetos Raúl Herrera A.
Ingreso , proceso y salida de datos
PROGRAMACION.
Convenciones de nomenclatura y diseño
Tema 6: Elementos de programación adicionales
Introducción a JAVA COMP 250.
Estructuras de Control en Visual Basic.net
Operadores Java es un lenguaje rico en operadores, que son casi idénticos a los de C/C++.
Conceptos Básicos Prof. Carlos Rodríguez Sánchez
Repaso Programacion en C
Introducción a la Programación Multimedial
Críticas al positivismo jurídico según F.A. Hayek
Conceptos básicos de programación
MANEJO DE ARRELOGS EN C Clase 8: Arreglos.
Lenguaje C en pocas palabras
Estructuras de Control en Visual Basic.net
Algunas Características de C++ no presentes en C
Definición y Conversión de datos
¿Qué es un OPERADOR? “Un operador es un elemento de programa que se aplica a uno o varios operandos en una expresión o instrucción. Los operadores que.
Programación orientada a objetos
Algunas Características de C++ no presentes en C
Compuertas Lógicas
Sonia Rueda Herencia y Polimorfismo
Constantes y variables
Bucles y estructuras de decisión
Comprueba si una u otra condición se cumple o no.
UNIVERSIDAD NACIONAL DE LOJA Área de la Educación, el Arte y la Comunicación Informática Educativa IV INGENIERIA DE SOFTWARE Taller de Análisis y Diseño.
EXPRESIONES Una expresión es una forma especial de asignación.
ALGORITMOS es un conjunto preescrito de instrucciones o reglas bien definidas, ordenadas y finitas que permite realizar una actividad mediante pasos.
Unidad 3. Introducción a la programación
Tema 7. Introducción a lenguaje de programación Visual Basic (clase 1)
Verificación y Validación de Software
Algunas Características de C++ no presentes en C
CONCEPTOS PRELIMINARES (Cont)
Introducción al lenguaje de programación. Introducción  Los lenguajes de programación son aplicaciones específicas que han sido pensadas y diseñadas.
ESTRUCTURAS DE CONTROL EN VISUAL BASIC.NET Prof.: Rafael Mourglia.
Ciclo de vida del Software
Tamaño de muestra Ecología Marina. Una población se define como un conjunto de individuos de una especie que habita un área determinada. Los métodos disponibles.
Criterios Evaluación Portafolio de evidencias 5 Mapa conceptual 10 Practicas 30 Examen teórico 20 Analizador Sem. 35.
 La minería de datos o exploración de datos (es la etapa de análisis de "Knowledge Discovery in Databases" o KDD) es un campo de la estadística y las.
Testing basado en sintaxis: Introducción
Criterios cobertura de grafos: código fuente
Automatización del testing
Características de “C”
Criterios cobertura de grafos: casos de uso
Criterios cobertura de grafos: introducción
Fundamentos de la Programación I
Testing basado en sintaxis: Gramáticas en espacios de inputs
Criterios cobertura de grafos: especificaciones
Manuel Núñez Especificación, Validación y Testing
Tema 3: Operadores Antonio J. Sierra.
Bucles y estructuras de decisión
PROGRAMACIÓN (2).
Informática Ingeniería en Electrónica y Automática Industrial
Algunas Características de C++ no presentes en C
Informática Ingeniería en Electrónica y Automática Industrial
NATURALEZA DE LOS DATOS Valores Numéricos Son los valores que se pueden hacer cálculos aritméticosritméticos Tipos de valores Entero Real Cadena ( “ h”
Programación Modular Programación de Computadoras - Hugo Vega Grupo2: Reina Rodríguez Miriam Salluca.
diseño de investigación
UNIVERSIDAD JUÁREZ AUTÓNOMA DE TABASCO Nombres: Isaac Sánchez García Teofilo Martinez Garcia Ricardo Del Carmen Paz López Vanesa Anahí Pérez Lizárraga.
Tratamientos secuenciales I
Algunas Características de C++ no presentes en C
PRUEBAS DE CAJA NEGRA. -Internationa Software Testing Qualification Board (ISTQB) Internationa Software Testing Qualification Board (ISTQB) Técnica de.
Transcripción de la presentación:

Testing basado en sintaxis: Gramáticas a partir de programas Manuel Núñez Especificación, Validación y Testing Estas transparencias están basadas en las desarrolladas por Ammann & Offutt como acompañamiento de su libro Introduction to Software Testing (2nd Edition)

Aplicación de testing basado en sintaxis a programas Los criterios basados en la sintaxis nacieron con los programas y se han utilizado, esencialmente, con programas. Los criterios que usan BNF se han usado, habitualmente, para testear compiladores. Los criterios de mutation testing se han usado, habitualmente, para testing unitario y para testear la integración de clases. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

BNF testing para compiladores Testear compiladores es MUY DIFÍCIL. Hay millones de programas correctos. Los compiladores deben reconocer y rechazar los programas incorrectos. Los criterios sobre BNF se pueden usar para generar programas que permitan testear las características que los compiladores deben procesar. Esta es una aplicación muy especializada y, por tanto, fuera del ámbito de este breve introducción al testing de software. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Gramáticas basadas en programas La aplicación original, y más conocida, de los métodos de testing basados en la sintaxis consiste en modificar programas. Los operadores modifican una cadena básica (programa que testeamos) para crear mutantes. Los mutantes deben compilar (deben ser cadenas válidas). Los mutantes no son tests, pero se usan para encontrar tests. Tras definir los mutantes, debemos buscar tests que provoquen el fallo de los mutantes al ejecutarlos. A este proceso se le llama matar mutantes. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Especificación, Validación y Testing (M. G. Merayo y M. Núñez) Matar mutantes Un test t mata a un mutante m de un cadena básica (programa) P sii el output observado al aplicar t a m es distinto del resultante de aplicar t a P. Si los operadores de mutación se diseñan bien entonces los tests resultantes suelen ser muy potentes. Se deben definir operadores distintos para distintos lenguajes de programación y distintos objetivos. Los testeadores añaden tests hasta que se matan todos los mutantes. Mutante muerto: Muere por un test. Mutante abortado: Sintácticamente ilegal. Mutante trivial: Lo mata casi cualquier test. Mutante equivalente: Ningún test lo puede matar (mismo comportamiento que el original). Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Especificación, Validación y Testing (M. G. Merayo y M. Núñez) Ejemplo Métodos mutados int Min (int A, int B) { int minVal; minVal = A; ∆ 1 minVal = B; if (B < A) ∆ 2 if (B > A) ∆ 3 if (B < minVal) minVal = B; ∆ 4 Bomb (); ∆ 5 minVal = A; ∆ 6 minVal = failOnZero (B); } return (minVal); } // end Min Método original int Min (int A, int B) { int minVal; minVal = A; if (B < A) minVal = B; } return (minVal); } // end Min Sustituir una variable con otra Sustituir operador Fallo inmediato si se alcanza Fallo inmediato si B==0, sino no hace nada 6 mutantes Cada uno representa un programa distinto Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Criterios de cobertura basado en sintaxis Mutation Coverage (MC): Para cada m  M, RT contiene exactamente un requisito: matar a m. El modelo RIPR que vimos en la introducción de la asignatura se adapta a este marco de la siguiente forma: Alcance: El test hace que se alcance la instrucción defectuosa (en este caso, la instrucción mutada). Infección: El test hace que esta instrucción produzca un estado incorrecto. Propagación: El estado incorrecto se propaga a un output incorrecto. Revelación: El testeador debe observar parte del output incorrecto. El modelo RIPR da lugar a dos variantes de cobertura. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Criterios de cobertura basado en sintaxis Matar mutantes fuertemente Dado un mutante m de un programa P y un test t, decimos que t strongly kills m sii el output de aplicar t a P es distinto del de aplicar t a m. Matar mutantes débilmente Dado un mutante m que modifica una posición l de un programa P y un test t, decimos que t weakly kills m sii el estado de la aplicación de t a P es distinto inmediatamente después de l del de la aplicación de t a m. Matar débilmente satisface alcance e infección pero no necesariamente propagación. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Especificación, Validación y Testing (M. G. Merayo y M. Núñez) Mutación débil Weak Mutation Coverage (WMC): Para cada m  M, RT contiene exactamente un requisito: matar débilmente a m. El apelativo “débil” denota que es más fácil matar mutantes bajo este esquema. También requiere menos análisis. Usualmente, hay solo unos pocos mutantes que se pueden matar débilmente pero que no se matan fuertemente (no hay propagación). Los estudios han mostrado que los conjuntos de tests que matan débilmente a todos los mutantes matan fuertemente a casi todos los mutantes. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Mutación débil: Ejemplo El primer mutante del ejemplo Min( ) es: El test completo que mata a este mutante es: Alcance: True //Siempre se llega a la instrucción Infección: A ≠ B Propagación: (B < A) = false // Salta la instrucción Test completo: true  (A ≠ B)  ((B < A) = false) ≡ (A ≠ B)  (B ≥A) ≡ (B > A) ¿Hay algún test que mate débilmente al mutante pero no fuertemente? int Min (int A, int B) { int minVal; minVal = A; minVal = B; if (B < A) } return (minVal); } // end Min Si, por ejemplo, A=5 y B=3. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Mutante equivalente: Ejemplo El tercer mutante del ejemplo Min( ) es: La condición para que tengamos infección es: (B < A) != (B < minVal) Sin embargo, la instrucción anterior es minVal = A. Sustituyendo en el predicado anterior: (B < A) != (B < A) Al ser una contradicción, ningún input mata a este mutante. int Min (int A, int B) { int minVal; minVal = A; if (B < A) if (B< minVal) minVal = B; } return (minVal); } // end Min Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Especificación, Validación y Testing (M. G. Merayo y M. Núñez) Fuerte vs. débil 1 boolean isEven (int X) 2 { 3 if (X < 0) 4 X = 0 - X; ∆ 4 X = 0; 5 if (double) (X/2) == ((double) X) / 2.0 6 return (true); 7 else 8 return (false); 9 } Alcance: X < 0 Infección: X != 0 (X = -6) lo mata bajo mutación débil Propagación : ((double) ((0-X)/2) == ((double) 0-X) / 2.0) != ((double) (0/2) == ((double) 0) / 2.0) Esto es, X no es par … Por tanto (X = - 6) no mata fuertemente al mutante Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Mutación para testear programas Pasos automatizados Programa testeado Crear mutantes Correr heurística equivalentes Generar tests Aplicar T a P no Aplicar T a los mutantes Definir límite Eliminar tests inefectivos ¿Límite alcanzado? ¿P (T) correcto ? si no Arreglar P no

¿Por qué funciona la mutación? Premisa Fundamental de Mutation Testing Si el software contiene un defecto (fault), usualmente habrá un conjunto de mutantes que pueden ser matados solamente por un test que también detecta este defecto. ¡Esto no es una verdad absoluta! Si es verdad que, habitualmente, los mutantes guían al testeador para que construya un conjunto de tests efectivos. Un problema muy interesante: encontrar un defecto y un conjunto de tests adecuados que no encuentren dicho defecto. Por supuesto, esto depende de los operadores de mutación…. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Diseño de operadores de mutación Si nos fijamos en métodos, los operadores de mutación son similares en distintos lenguajes de programación. Los operadores de mutación hacen una de las siguientes cosas: Imitan los errores típicos de los programadores (nombres incorrectos de variables). Alientan a usar unas heurísticas de test comunes (causar que las expresiones valgan cero). Los investigadores han diseñado montones de operadores y después han seleccionado, tras experimentación, los más útiles. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Diseño de operadores de mutación Operadores de mutación efectivos Si unos tests que se han creado específicamente para matar mutantes creados por unos operadores de mutación O = {o1, o2, …} también matan mutantes creados por todos los demás operadores con una alta probabilidad, entonces O define un conjunto efectivo de operadores de mutación. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Operadores de mutación en Java ABS –– Absolute Value Insertion AOR –– Arithmetic Operator Replacement ROR –– Relational Operator Replacement COR –– Conditional Operator Replacement SOR –– Shift Operator Replacement LOR –– Logical Operator Replacement ASR –– Assignment Operator Replacement UOI –– Unary Operator Insertion UOD –– Unary Operator Deletion SVR –– Scalar Variable Replacement BSR –– Bomb Statement Replacement Pasemos a ver definiciones completas Especificación, Validación y Testing (M. G. Merayo y M. Núñez)

Operadores de mutación en Java Cada expresión (y subexpresión) se sustituye por las funciones abs(), negAbs() y failOnZero(). 1. ABS –– Absolute Value Insertion: Ejemplos: a = m * (o + p); ∆1 a = abs (m * (o + p)); ∆2 a = m * abs ((o + p)); ∆3 a = failOnZero (m * (o + p)); Cada aparición de uno de los operadores aritméticos +,-,*,/, % se sustituye por los demás operadores. Además, también se sustituye por los operadores especiales leftOp y rightOp. 2. AOR –– Arithmetic Operator Replacement: Ejemplos: a = m * (o + p); ∆1 a = m + (o + p); ∆2 a = m * (o * p); ∆3 a = m leftOp (o + p);

Operadores de mutación en Java Cada aparición de uno de los operadores relacionales <, ≤, >, ≥, =, ≠ se sustituye por los demás operadores y por el operador falseOP. 3. ROR –– Relational Operator Replacement: Ejemplos: if (X <= Y) ∆1 if (X > Y) ∆2 if (X < Y) ∆3 if (X falseOp Y) // devuelve false Cada aparición de uno de los operadores lógicos (and - &&, or - || , and sin evaluación condicional - &, or sin evaluación condicional - |, no equivalente - ^) se sustituye por los demás operadores. Además, también se sustituye por by falseOp, trueOp, leftOp y rightOp. 4. COR –– Conditional Operator Replacement: Ejemplos: if (X <= Y && a > 0) ∆1 if (X <= Y || a > 0) ∆2 if (X <= Y leftOp a > 0) // devuelve resultado // cláusula izquierda

Operadores de mutación en Java Cada aparición de uno de los operadores <<, >>, >>> se sustituye por los demás operadores y por el operador leftOP. 5. SOR –– Shift Operator Replacement: Ejemplos: byte b = (byte) 16; b = b >> 2; ∆1 b = b << 2; ∆2 b = b leftOp 2; // resultado es b Cada aparición de uno de los operadores lógicos (bitwise and - &, bitwise or - | , or exclusivo - ^) se sustituye por los demás operadores. Además, también se sustituye por leftOp y rightOp. 6. LOR –– Logical Operator Replacement: Ejemplos: int a = 60; int b = 13; int c = a & b; ∆1 int c = a | b; ∆2 int c = a rightOp b; // resultado es b

Operadores de mutación en Java Cada aparición de uno de los operadores de asignación +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>= se sustituye por los demás. 7. ASR –– Assignment Operator Replacement: Ejemplos: a = m * (o + p); ∆1 a += m * (o + p); ∆2 a *= m * (o + p); Cada operador unario (+ y – aritméticos, ! condicional, ~ lógico) se inserta delante de cada expression del tipo adecuado. 8. UOI –– Unary Operator Insertion: Ejemplos: a = m * (o + p); ∆1 a = m * - (o + p); ∆2 a = -(m * (o + p));

Operadores de mutación en Java Se borra cada operador unario (+ y – aritméticos, ! condicional, ~ lógico). 9. UOD –– Unary Operator Deletion: Ejemplos: if !(X <= Y && !Z) ∆1 if (X > Y && !Z) ∆2 if !(X < Y && Z) Cada variable se sustituye por todas las demás del mismo tipo y que estén declaradas en el mismo entorno. 10. SVR –– Scalar Variable Replacement: Ejemplos: a = m * (o + p); ∆1 a = o * (o + p); ∆2 a = m * (m + p); ∆3 a = m * (o + o); ∆4 p = m * (o + p);

Operadores de mutación en Java Cada instrucción se sustituye por una función especial Bomb(). 11. BSR –– Bomb Statement Replacement: Ejemplos: a = m * (o + p); ∆1 Bomb() //lanza una excepción cuando se //ejecuta

Subsunción de otros criterios Se considera que mutation testing es el criterio de testing más potente. ¡Y también el más caro! De largo, es el que necesita más requisitos de testing (uno por mutante). Usualmente, también es el que más tests necesita. Mutación subsume otros criterios al incluirlos implícitamente como operadores de mutación específicos. Especificación, Validación y Testing (M. G. Merayo y M. Núñez)