Está en la página 1de 38

Mantenimiento Avanzado de Sistemas de Informacin

Pruebas del Software

Dr. Macario Polo Usaola Departamento de Informtica Paseo de la Universidad, 4 13071-Ciudad Real macario.polo@uclm.es

ndice
1. Introduccin.......................................................................................... 3 1.01 El proceso de pruebas en el ciclo de vida ..................................... 3 Pruebas de requisitos ............................................................ 4 Pruebas del diseo ................................................................ 5 Revisiones e inspecciones del cdigo fuente......................... 6

1.01.1 1.01.2 1.01.3 1.02 2.

Automatizacin de las pruebas ..................................................... 7

Pruebas estructurales o de caja blanca ............................................... 8 2.01 Criterios de cobertura.................................................................... 8 Cobertura de sentencias ........................................................ 8 Cobertura de decisiones ........................................................ 9 Cobertura de condiciones ...................................................... 9 Cobertura de condiciones mltiples ....................................... 9 Cobertura de condiciones/decisiones .................................... 9 Cobertura de caminos............................................................ 9 Cobertura de funciones.......................................................... 9 Cobertura de llamadas........................................................... 9 Cubrimiento de bucles ......................................................... 10 Cubrimiento de carrera ........................................................ 10 Cobertura de operadores relacionales ................................. 10 Cobertura de tablas.............................................................. 10

2.01.1 2.01.2 2.01.3 2.01.4 2.01.5 2.01.6 2.01.7 2.01.8 2.01.9 2.01.10 2.01.11 2.01.12 2.02

Mutacin...................................................................................... 10 Proceso de pruebas basado en mutacin............................ 11 Operadores de mutacin...................................................... 12

2.02.1 2.02.2 2.03

Generacin de casos de prueba con algoritmos de minimizacin 14

2.03.1 2.03.2 2.03.3 3.

Bsqueda Tab.................................................................... 14 Algoritmos Genticos (I)....................................................... 16 Algoritmos Genticos (II)...................................................... 17

Pruebas funcionales o de caja negra ................................................. 17 3.01 Generacin de casos de prueba ................................................. 17 Secuencias de mtodos ....................................................... 17 Especificaciones formales o semiformales .......................... 18

3.01.1 3.01.2

3.01.3 3.01.4 3.02

Mtodo ASTOOT ................................................................. 21 Obtencin automtica de especificaciones algebraicas....... 24

Pruebas a partir de modelos ....................................................... 25 Diagramas de clases UML ................................................... 25 Criterios de cobertura de pruebas para diseos UML.......... 28 Diagramas de estados ......................................................... 29 En otros diagramas .............................................................. 29

3.02.1 3.02.2 3.02.3 3.02.4 3.03

Pruebas de componentes ........................................................... 31 Uso de BIT wrappers ........................................................... 31 Mutacin de interfaces ......................................................... 33

3.03.1 3.03.2 4. 5.

Resultados experimentales ................................................................ 34 Referencias ........................................................................................ 36

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

1. INTRODUCCIN
La fase de pruebas es una de las ms costosas del ciclo de vida software. En sentido estricto, deben realizarse pruebas de todos los artefactos generados durante la construccin de un producto, lo que incluye especificaciones de requisitos, casos de uso, diagramas de diversos tipos y, por supuesto, el cdigo fuente y el resto de productos que forman parte de la aplicacin (p.ej., la base de datos). Obviamente, se aplican diferentes tcnicas de prueba a cada tipo de producto software.

1.01 El proceso de pruebas en el ciclo de vida


El estndar ISO/IEC 12207 (ISO/IEC 1995) identifica tres grupos de procesos en el ciclo de vida software: Procesos principales, grupo en el que incluye los procesos de Adquisicin, Suministro, Desarrollo, Operacin y Mantenimiento. Procesos de la organizacin, en donde se encuentran los procesos de Gestin, Mejora, Infraestructura y Formacin. Procesos de soporte o auxiliares, en donde estn los procesos de Documentacin, Gestin de la Configuracin, Auditora, Resolucin de Problemas, Revisin Conjunta, Aseguramiento de la Calidad, Verificacin, Validacin, No define, como vemos, un proceso de Pruebas como tal, sino que aconseja, durante la ejecucin de los procesos principales o de la organizacin, utilizar los procesos de soporte. Entre stos se encuentran los procesos de Validacin y de Verificacin: El proceso de Validacin tiene como objetivo determinar si los requisitos y el sistema final cumplen los objetivos para los que se construy el producto, respondiendo as a la pregunta el producto es correcto? El proceso de Verificacin intenta determinar si los productos software de una actividad se ajustan a los requisitos o a las condiciones impuestas en actividades anteriores. De este modo, la pregunta a la que responde este proceso es se est construyendo el producto correctamente?

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Del proceso de Verificacin se observa la importancia de verificar cada uno de los productos que se van construyendo, bajo la asuncin de que si lo que se va construyendo es todo ello correcto, tambin lo ser el producto final. Igualmente, se observa que el proceso de Validacin resalta la importancia de comprobar el cumplimiento de los objetivos de los requisitos y del sistema final, de suerte que podra construirse un Plan de pruebas de aceptacin desde el momento mismo de tener los requisitos, que sera comprobado al finalizar el proyecto. Si tras la fase de requisitos viniese una segunda de diseo a alto nivel del sistema, tambin podra prepararse un Plan de pruebas de integracin, que sera comprobado tras tener codificados los diferentes mdulos del sistema. Esta correspondencia entre fases del desarrollo y tipos de pruebas produce el llamado modelo en V, del que se muestra un ejemplo en la Figura 1.
Requisitos Pruebas de aceptacin

Diseo de alto nivel

Pruebas de sistema

Diseo de bajo nivel

Pruebas de integracin

Cdigo

Pruebas unitarias

Figura 1. Modelo en V

1.01.1 Pruebas de requisitos La prueba de requisitos pretende comprobar los tres principales atributos de calidad de los requisitos, con el fin de detectar tantos errores como sea posible y cuanto antes: correccin (carencia de ambigedad), complecin (especificacin completa y clara del problema) y consistencia (que no haya requisitos contradictorios).

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

(Bashir and Goel 2000) proponen la utilizacin de una Matriz de Prueba de Requisitos (RTM: Requirements Testing Matrix), en la que se lista cada requisito junto a sus casos de uso y casos de prueba:
Requisito Casos de uso Casos de prueba Id del prototipo en que se incluye Validado con el usuario?

Tabla 1. Tabla RTM (Matriz de Tabla de Requisitos)

1.01.2 Pruebas del diseo La fase de diseo tiene como objetivo generar un conjunto de especificaciones completas del sistema que se va a implementar, transformando los requisitos en un Plan de implementacin. La prueba del diseo debe comprobar su consistencia, complecin, correccin, factibilidad (es decir, que el diseo sea realizable) y trazabilidad (es decir, que podamos navegar desde un requisito hasta el fragmento del diseo en que ste se encuentra). Las actividades que proponen (Bashir and Goel 2000) para este tipo de pruebas se muestran en la Figura 2.

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Particionar requisitos

Seleccionar siguiente conjunto de requisitos

Revisar diagramas

Construir prototipo

Probar cumplimiento de requisitos funcionales

Probar cumplimiento de requisitos de recursos

Probar cumplimiento de requisitos de rendimiento

Figura 2. Actividades para la prueba del diseo

1.01.3 Revisiones e inspecciones del cdigo fuente Las revisiones e inspecciones de cdigo fuente son una tcnica para la deteccin manual de errores en el cdigo (Bashir and Goel 2000). Se trabaja bajo el principio de que cuatro ojos ven ms que dos, de tal manera que el mtodo de trabajo consistir, bsicamente, en pasar el cdigo escrito por un programador a un tercero o grupo de terceros, que tratar de encontrar posibles errores, faltas de adecuacin al estilo de codificacin utilizado por la organizacin, etc. Para ello suelen utilizarse listas de comprobacin (checklists), que enumeran defectos y en los que el revisor anota su presencia o ausencia. En (Fox 1998) puede consultarse una lista de comprobacin de errores tpicos del lenguaje Java, entre los que se incluyen el control de overflows y underflows, restriccin adecuada del acceso a los miembros de las clases, control de apertura y cierre de ficheros, etc.

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

1.02 Automatizacin de las pruebas


(Rice 2002) enumera y explica los diez retos ms importantes en la automatizacin del proceso de pruebas. De acuerdo con este autor, stos son los siguientes: Falta de herramientas, debida fundamentalmente a su elevado precio o a que las existentes no se ajusten al propsito o entorno para el que se necesitan. La primera razn parece deberse a la no mucha importancia que habitualmente se le da a la fase de pruebas, y eso que el costo de corregir un error puede, en muchos casos, superar al de la licencia de uso. Sera conveniente evaluar el coste de correccin de defectos del software entregado y compararlo con el de la licencia de la herramienta de pruebas. Falta de compatibilidad e interoperabilidad entre herramientas. Falta de proceso de gestin de la configuracin. Igual que las diferentes versiones del cdigo fuente, las pruebas, especialmente las de regresin, deben someterse a un control de versiones. Recurdese que el proceso de Gestin de la Configuracin es uno de los procesos de soporte del estndar ISO/IEC 12207 (ISO/IEC 1995), que debera utilizarse en la ejecucin de los procesos principales, y muy especialmente en los de Desarrollo y Mantenimiento. Falta de un proceso bsico de pruebas y de conocimiento de qu es lo que se debe probar. Falta de uso de las herramientas de prueba que ya se poseen, bien por su dificultad de uso, por falta de tiempo para aprender a manejarla, por falta de soporte tcnico, obsolescencia, etc. Formacin inadecuada en el uso de la herramienta. La herramienta no cubre todos los tipos de prueba que se desean (correccin, fiabilidad, seguridad, rendimiento, etc.). Obviamente, a la hora de elegir la herramienta, deberan tenerse priorizados los tipos de pruebas, y entonces hacer la eleccin de la herramienta basados en esto. A veces tambin es necesario utilizar no una, sino varias herra-

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

mientas de prueba, as como tener en cuenta que es imposible automatizar el 100% de las pruebas. Falta de soporte o comprensin por parte de los jefes, debido otra vez a la escasa importancia que habitualmente se le da a la fase de pruebas. Organizacin inadecuada del equipo de pruebas. Adquisicin de una herramienta inadecuada.

2. PRUEBAS ESTRUCTURALES O DE CAJA BLANCA


Las pruebas de caja blanca realizan un seguimiento del cdigo fuente segn va ejecutando los casos de prueba, de manera que se determinan de manera concreta las instrucciones, bloques, etc. en los que existen errores. Cuando se pasan casos de prueba al programa que se est probando, es conveniente conocer qu porcentaje del programa se ha ejecutado, de manera que estemos prximos a asegurar que todo l es correcto (evidentemente, es imposible alcanzar una certeza del 100%). Existen varias formas de medir la cobertura lograda en el programa por los casos de prueba, algunas de las cuales se presentan en el siguiente epgrafe.

2.01 Criterios de cobertura


De acuerdo con (Cornett 2002), el anlisis de cobertura del cdigo es el proceso de: Encontrar fragmentos del programa que no son ejecutados por los casos de prueba. Crear casos de prueba adicionales que incrementen la cobertura. Determinar un valor cuantitativo de la cobertura (que es, de manera indirecta, una medida de la calidad del programa). Adicionalmente, el anlisis de cobertura tambin permite la identificacin de casos de prueba redundantes, que no incrementan la cobertura. 2.01.1 Cobertura de sentencias Comprueba el nmero de sentencias ejecutables que se han ejecutado.

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

2.01.2 Cobertura de decisiones Comprueba el nmero de decisiones ejecutadas, considerando que se ha ejecutado una decisin cuando se han recorrido todas sus posible ramas (la que la hace true y la que la hace false, pero tambin todas las posibles ramas de un switch). 2.01.3 Cobertura de condiciones Comprueba el nmero de condiciones ejecutadas, entendiendo que se ha ejecutado una condicin cuando se han ejecutado todas sus posibles ramas. 2.01.4 Cobertura de condiciones mltiples Comprueba el nmero de condiciones mltiples ejecutadas, considerando que se ha ejecutado una condicin mltiple cuando se han ejecutado todas sus correspondientes ramas con todas las posibles variantes de la instruccin condicional. 2.01.5 Cobertura de condiciones/decisiones Comprueba el nmero de condiciones y decisiones que se han ejecutado. 2.01.6 Cobertura de caminos Comprueba el nmero de caminos linealmente independientes que se han ejecutado en el grafo de flujo de la unidad que se est probando. El nmero de caminos linealmente independientes coincide con la complejidad ciclomtica de McCabe. 2.01.7 Cobertura de funciones Comprueba el nmero de funciones y procedimientos que han sido llamados. 2.01.8 Cobertura de llamadas Comprueba el nmero de llamadas a funciones y procedimientos que se han ejecutado. No debe confundirse con la cobertura de funciones: en la cobertura de funciones contamos cuntas funciones de las que hay en nuestro pro-

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

grama han sido llamadas, mientras que la cobertura de llamadas cuenta cuntas de las llamadas a funciones que hay en el programa se han ejecutado. 2.01.9 Cubrimiento de bucles Comprueba el nmero de bucles que han sido ejecutados cero veces (excepto para bucles do..while), una vez y ms de una vez. 2.01.10 Cubrimiento de carrera

Comprueba el nmero de tareas o hilos que han ejecutado simultneamente el mismo bloque de cdigo. 2.01.11 Cobertura de operadores relacionales

Comprueba si se han ejecutado los valores lmite en los operadores relacionales (>, <, >=, <=), ya que se asume la hiptesis de que estas situaciones son propensas a errores. 2.01.12 Cobertura de tablas

Comprueba si se ha hecho referencia a todos los elementos de los arrays.

2.02 Mutacin
Un mutante es una copia del programa que se est probando (programa original) al que se le ha introducido un nico y pequeo cambio (normalmente sintctico, como la sustitucin de un signo + por un *), lo que supone tener una versin defectuosa del programa original. Supongamos que ejecutamos un mismo caso de prueba en el programa original y en el mutante, y supongamos adems que la salida del programa original es correcta, y que la salida del mutante difiere en algo de la salida del original. Entonces, podremos asegurar que, para ese caso de prueba, la instruccin mutada es correcta en el programa original. Si a ambos programas les pasamos una batera de casos de prueba y siempre obtuviramos resultados correctos en el original e incorrectos en el mutante, podramos afirmar con poco temor a equivocarnos que la instruccin mutada de nuestro programa es correcta. Un mutante que produce que produce la misma salida que el programa original se dice que est vivo, y muerto si su salida es diferente. Cuantos ms mu-

10

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

tantes consigamos matar, estaremos logrando mayor cobertura del programa original, lo que de manera indirecta es una medida de la calidad del programa. 2.02.1 Proceso de pruebas basado en mutacin La Figura 3 muestra el proceso de mutacin propuesto por (Offut 1995). Las lneas punteadas indican tareas manuales, mientras que las de trazo continuo son tareas automatizables. Inicialmente se genera el conjunto de mutantes, el conjunto de casos de prueba y se define un umbral que representa el porcentaje mnimo de mutantes muertos que debe alcanzarse. Entonces se ejecutan los casos de prueba sobre el programa original y sobre los mutantes, y se calcula el porcentaje de mutantes muertos. Si no se ha alcanzado el umbral previamente definido, se eliminan los casos de prueba que no han matado mutantes y se generan casos de prueba nuevos, especialmente dirigidos a matar los mutantes que han permanecido vivos. Tradicionalmente, se considera que para matar a un mutante deben producirse tres condiciones: Alcance: la sentencia mutada debe ser ejecutada por el caso de prueba. Necesidad: entre la entrada y la salida del programa debe crearse un estado intermedio errneo. Suficiencia: el estado incorrecto debe propagarse hasta la salida del programa. La condicin de suficiencia puede ser difcil de conseguir en muchas ocasiones, lo que puede dificultar la obtencin de casos de prueba a un coste razonable. La mutacin dbil se queda en la condicin de necesidad para determinar que un caso de prueba ha matado a un mutante: compara el estado intermedio del mutante y el del programa original inmediatamente despus de haber ejecutado la instruccin mutada, marcando el mutante como muerto si los estados son diferentes. Se ha comprobado experimentalmente que esta tcnica puede ahorrar hasta el 50% del coste de las pruebas sin degradar excesivamente su calidad.

11

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Progama original P

Crear mutantes M

Crear casos de prueba T

Ejecutar T sobre P

Definir umbral

Ejecutar T sobre cada mutante vivo

No Eliminar los casos de prueba ineficientes

Corregir P

Se alcanz el umbral? S

No

P(T) es correcta? S

Fin

Figura 3. Proceso de mutacin propuesto por (Offut 1995)

2.02.2 Operadores de mutacin La generacin de mutantes se consigue aplicando operadores de mutacin al cdigo fuente del programa que queremos probar. La Tabla 2 muestra algunos de los operadores de mutacin citados en (Offut, Rothermel et al. 1996).
Operador ABS ACR AOR CRP ROR RSR SDL UOI Descripcin Sustituir una variable por el valor absoluto de dicha variable Sustituir una referencia variable a un array por una constante Sustitucin de un operador aritmtico Sustitucin del valor de una constante Sustitucin de un operador relacional Sustitucin de la instruccin Return Eliminacin de una sentencia Insercin de operador unario (p.ej.: en lugar de x, poner x)

Tabla 2. Algunos operadores de mutacin clsicos

El nmero de mutantes que puede generarse a partir de un programa sencillo, de pocas lneas de cdigo, es muy grande (pinsese que el operador

12

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

AOR, por ejemplo, puede aplicarse a cada aparicin de un operador aritmtico en el programa original), resultando tambin muy costosas tanto la ejecucin de los casos de prueba con cada mutante como la comprobacin de la salida del programa. Por ello, se han realizado algunos estudios encaminados a disminuir los costes de este tipo de pruebas, evidencindose que, aplicando pocos operadores, se pueden conseguirse los mismos resultados que si se aplicaran muchos. Los operadores ms efectivos son el ABS, 0 (sustitucin de una variable por el valor 0), <0 (sustitucin de una variable por un valor menor que 0), >0 (sustitucin de una variable por un valor mayor que 0), AOR, ROR y UOI. Adems, tambin se han propuesto operadores especficos para programas escritos en lenguajes orientados a objeto, algunos de los cuales se muestran en la Tabla 3 (Kim, Clark et al. 2000).
Operador AMC (Access Modifier Change) AOC (Argument Order Change) CRT (Compatible Reference Type Replacement) EHC (Exception Handling Change) EHR (Exception Handgling Removal) HFA (Hiding Field variable Addition) MIR (Method Invocation Replacement) OMR (Overriding Method Removal) POC (Parameter Order Change) SMC (Static Modifier Change) Descripcin Reemplazo del modificador de acceso (por ejemplo: ponemos private en lugar de public) Cambio del orden de los argumentos pasados en la llamada a un mtodo (p.ej.: en lugar de Persona p=new Persona(Paco, Pil) poner Persona p=new Persona(Pil, Paco) Sustituir una referencia a una instancia de una clase por una referencia a una instancia de una clase compatible (p.ej.: en vez de poner Persona p=new Empleado(), poner Persona p=new Estudiante()). Cambiar una instruccin de manejo de excepciones (try...catch) por un sentencia que propague la excepcin (throw), y viceversa Eliminacin de una instruccin de manejo de excepciones Aadir en la subclase una variable con el mismo nombre que una variable de su superclase Reemplazar una llamada a un mtodo por una llamada a otra versin del mismo mtodo Eliminar en la subclase la redefinicin de un mtodo definido en una superclase Cambiar el orden de los parmetros en la declaracin de un mtodo (p.ej.: poner Persona(String apellidos, String nombre) en vez de Persona(String nombre, String apellidos) Aadir o eliminar el modificador static

Tabla 3. Algunos operadores de mutacin para orientacin a objetos

Los operadores de mutacin deben ser aplicados segn el contexto del lugar del cdigo fuente en el que se vaya a realizar la mutacin. Si esto no se hiciera as, podran generarse multitud de mutantes funcionalmente equivalentes al programa original, otros que ni siquiera compilaran, etc.

13

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

2.03 Generacin de casos de prueba con algoritmos de minimizacin


De entre los criterios de cobertura enumerados en la seccin 2.01, es de destacar la dificultad de conseguir valores aceptables para la cobertura de decisiones, condiciones y condiciones/decisiones. Pinsese, por ejemplo, en la dificultad de encontrar valores que satisfagan una condicin tan simple como if (a<10) si esta instruccin se encuentra a una distancia computacional considerable de la entrada del programa. La generacin de casos de prueba con algoritmos de minimizacin construye una funcin de minimizacin para cada condicin, aplicando entonces diferentes heursticas para conseguir la cobertura, en funcin de los datos recogidos durante la ejecucin de cada caso. A continuacin se hace una revisin rpida de tres mtodos basados en algoritmos de minimizacin: uno basado en Bsqueda Tab y dos en algoritmos genticos, si bien existen otras posibilidades, como el uso de Simmulated Annealing (Tracey, Clark et al. 1998) o enfoques hbridos como el propuesto por (Lapierre, Merlo et al. 1999). 2.03.1 Bsqueda Tab (Daz, Tuya et al. 2003) proponen la utilizacin de un algoritmo basado en Bsqueda Tab para lograr amplia cobertura de decisiones (Figura 4). La Bsqueda Tab se basa en el algoritmo de los k-vecinos junto al mantenimiento en memoria de una lista tab que evita repetir la bsqueda dentro de un rea del espacio de soluciones. Al algoritmo se le deben suministrar algunos parmetros, como la funcin objetivo (que mide el coste de la solucin), la estrategia para seleccionar vecinos y la memoria del algoritmo.

14

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Generar una solucin aleatoria como solucin actual Calcular coste de la solucin actual y almacenarlo como mejor coste Aadir la solucin actual como nueva solucin Aadir la nueva solucin a la lista tab do Calcular los vecinos candidatos Calcular el coste de los candidatos Almacenar el mejor candidato como nueva solucin Aadir la nueva solucin a la lista tab if coste de nueva solucin < mejor coste Almacenar nueva solucin como mejor solucin Almacenar coste de la nueva solucin como mejor coste end_if Almacenar nueva solucin como solucin actual while no se alcance el criterio de parada Figura 4. Algoritmo de bsqueda tab

Puesto que el objetivo de estos autores es alcanzar la mayor cobertura posible, utilizan un grafo que representa el flujo de control del programa, en cuyos nodos se anota si el propio nodo ha sido alcanzado, cuntas veces lo ha sido y cul es el mejor caso de prueba que lo ha alcanzado. Cuando no hay ramas inalcanzables, el mximo valor posible para la cobertura es el 100%, mientras que ser desconocido en caso de que las haya. Por este motivo establecen como criterio de parada o haber alcanzado todas las ramas, o que el algoritmo haya superado un nmero de iteraciones prefijado. Adems, cada solucin se caracteriza por su conjunto de valores de entrada. El coste de una solucin, fundamental para que el algoritmo funcione eficazmente, se calcula considerando que el mejor caso de prueba es aquel que tiene ms posibilidades de que sus vecinos permuten entre ramas o, lo que es lo mismo, aquel que alcanza el nodo con valores lmite. Por ejemplo, si la condicin es x!=y, la funcin de coste ser |x-y| (vase la referencia para conocer el resto de detalles de clculo de la funcin de coste). Para calcular los vecinos candidatos, los autores se basan en que, si un caso de prueba cubre al padre de un nodo pero no a su hijo, entonces puede encontrarse un vecino que alcance al hijo utilizando el caso que cubre al padre

15

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

a partir de la mejor solucin. A partir de sta generan 2n vecinos cercanos y 2n vecinos lejanos (donde n es el nmero de variables de entrada del programa). Los candidatos se comprueban frente a la lista tab, rechazndose aquellos que ya existen. En la siguiente iteracin se repite el proceso, con la diferencia de que el nodo objetivo puede haber cambiado si alguno de los candidatos alcanz el entonces nodo objetivo. 2.03.2 Algoritmos Genticos (I) (Pargas, Harrold et al. 1999) utilizan el algoritmo mostrado en la Figura 5 para lograr criterios de cobertura altos. En la primera lnea se calcula CDGPaths, que representa el grafo de dependencias de control del programa que se va a probar. Un grafo de dependencia de control es un grafo dirigido acclico cuyos nodos representan sentencias y cuyos arcos representan dependencias de control entre sentencias. Un nodo Y depende por control de otro X si y slo si: (1) cualquier nodo intermedio en el camino de X a Y est postdominado por Y; y (2) X no est postdominado por Y. Se dice adems que un nodo X est postdominado por otro Y si para llegar desde X a la salida es preciso pasar siempre por Y. A continuacin se inicializa Scoreboard, que guarda el registro de los requisitos de prueba (TestReq) satisfechos. Scoreboard puede ser un vector de bits si se desea lograr cobertura de sentencias, un vector de enteros si deseamos conocer la frecuencia de ejecucin de cada sentencia o, en general, una estructura de datos adecuada al criterio de obertura considerado. El siguiente paso es la generacin de la poblacin inicial (conjunto inicial de los valores de entrada). A continuacin (bucle de las lneas 4 a 14), comienza el proceso de generacin de los casos de prueba, bastante legible sin mayor explicacin. Como excepcin, hay que resaltar que el clculo del fitness se hace en funcin del nmero de nodos de CDGPaths alcanzados por el caso de prueba teniendo en cuenta el requisito de prueba actual (variable r en el algoritmo).

16

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

1. Crear CDGPaths 2. Crear e inicializar Scoreboard 3. Generar CurPopulation 4. while haya requisitos de prueba no marcados and se est en tiempo 5. 6. 7. 8. 9. 10. 11. 12. 13. seleccionar un requisito de prueba r del conjunto TestReq while r no est marcado and no se supere el mximo de intentos calcular el fitness de de CurPopulation usando CDGPaths ordenar CurPopulation segn su fitness seleccionar los padres para crear la NewPopulation generar NewPopulation ejecutar el programa con cada elemento de NewPopulation actualizar Scoreboard y marcar aquellos requisitos que se hayan satisfecho endwhile

14. endwhile 15. final = conjunto de casos de prueba que satisfacen TestReq 16. devolver (TestReq, final) Figura 5. Algoritmo de generacin de casos de prueba de (Pargas, Harrold et al. 1999)

2.03.3 Algoritmos Genticos (II) El trabajo de (Michael, McGaw et al. 2001) es sustancialmente bastante parecido al presentado en la seccin anterior, lo que no es de extraar al estar ambos apoyados en algoritmos genticos: utilizan una poblacin inicial, un conjunto de requisitos de prueba (cobertura de decisiones/condiciones, en este caso), una funcin de fitness, un mtodo de cruce de individuos, etc. En este trabajo, sin embargo, no utilizan grafo de dependencias de control, por lo que el valor del fitness se calcula de una manera ms parecida al trabajo antes mencionado de la Bsqueda Tab (Daz, Tuya et al. 2003).

3. PRUEBAS FUNCIONALES O DE CAJA NEGRA


3.01 Generacin de casos de prueba
3.01.1 Secuencias de mtodos En el contexto de las pruebas de sistemas orientados a objetos, (Kirani and Tsai 1994) consideran la secuencia como un concepto fundamental para la prueba de clases. Una secuencia representa el orden correcto en el que los

17

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

mtodos pblicos de una clase pueden ser invocados. De acuerdo con estos autores, una de las aplicaciones de las secuencias es la prueba de clases a partir de su especificacin como una mquina de estados. As, puede utilizarse la especificacin del comportamiento de una cierta clase en forma de mquina de estados para generar casos de prueba, ejecutarlos y medir nuevos criterios de cobertura. En el ejemplo de la Figura 6, se conseguira una cobertura completa de estados con la secuencia m1.m2.m3.m4, mientras que deberan ejecutarse otras secuencias para lograr cobertura de transiciones o cobertura de caminos. A partir de aqu surgen con facilidad otros criterios de cobertura, como la ejecucin de cada camino cero veces, una vez y ms de una vez, cobertura de guardas, de acciones, etc.
m3

m3 m1 s0 s1 m2 s2 m4 m4

s3

m3

s4

m4

Figura 6. Mquina de estados para una cierta clase

3.01.2 Especificaciones formales o semiformales Lo ms interesante del trabajo de (Tse and Xu 1996) es, por un lado, la explicacin que ofrecen acerca de la especificacin formal de una clase y, por otro, la utilizacin de esta especificacin para obtener el espacio de estados de la clase y generar casos de prueba. De manera general, una clase puede especificarse utilizando combinadamente dos formas de representacin: una capa funcional, en la que se representan los valores abstractos de los objetos de la clase, y una capa de objeto, en la que se anotan la clase y sus operaciones con precondiciones, postcondiciones e invariantes.

18

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

La Figura 7 muestra las dos capas de una clase Account, que podra representar una cuenta bancaria, con un determinado lenguaje de especificacin (aunque lo cierto es que existen muchos ms para representar lo mismo, como se ver ms adelante en, por ejemplo, la Figura 9).
Capa funcional de una clase module ACCOUNT is including MONEY . sort AccountSort . var X : AccountSort . var M : Money . var N : Money . let creditLimit = 1000 . op empty : -> AccountSort . op creditS : AccountSort Money -> AccountSort . op balance : AccountSort -> Money . eq balance(empty) = 0 . eq balance(creditS(X, M)) = M + balance(X) . op charge : AccountSort Money -> Money . eq charge(empty, N) = 0 . ceq charge(creditS(X, M), N) = N * 0.05 if N < 200 and balance(creditS(X, M)) < 0 . ceq charge(creditS(X, M), N) = 10 if N >= 200 and balance(creditS(X, M)) < 0 . ceq charge(creditS(X, M), N) = 0 if balance(creditS(X, M)) >= 0 . op debitS : AccountSort Money -> AccountSort . eq debitS(empty, N) = creditS(empty, - N) . eq debitS(creditS(X, M), N) = creditS(X, (M - N - charge(creditS(X, M), N))) . endmodule Figura 7. Capas funcional y de objeto de una clase. Figura tomada de (Tse and Xu 1996) Capa de objeto de la misma clase class Account is based on sort AccountSort . invariant {balance(self) >= - creditLimit} . constructor Account() ensure {balance(result) == balance(empty)} . method credit(M : Money) require {M > 0} . ensure {balance(post-self) == balance(creditS(pre-self, M))} . method debit(M : Money) require {M > 0 and balance(debitS(pre-self, M)) >= creditLimit} . ensure {balance(post-self) == balance(debitS(pre-self, M))} . method findBalance() : Money ensure {result == balance(pre-self) and balance(post-self) == balance(pre-self)} . endclass

La capa funcional incluye la descripcin de los tipos importados (including MONEY), el nombre del tipo (sort AccountSort), las posibles variables que se utilicen a continuacin (var X, M, N) y un conjunto de clusulas que especifican los resultados de las operaciones: op representa la signatura de la operacin. Por ejemplo: op charge : AccountSort Money -> Money indica que la operacin charge toma un parmetro de tipo AccountSort y otro de tipo Money y que devuelve un Money.

19

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

eq representa propiedades de las operaciones descritas mediante ecuaciones. Por ejemplo, eq balance(empty) = 0 indica que el resultado de ejecutar la operacin balance (en ingls, saldo) sobre una cuenta creada con la operacin empty (en ingls, vaca), es cero; eq debitS(empty, N) = creditS(empty, - N) indica que sacar N euros de una cuenta vaca (cuyo saldo es cero) es lo mismo que sacar los mismos N euros a crdito.

ceq representa propiedades de las operaciones descritas mediante ecuaciones condicionales. Por ejemplo, ceq charge(creditS(X, M), N) = N * 0.05 if N < 200 and balance(creditS(X, M)) < 0 indica que sacar

N euros de una cuenta X de la que se han sacado a crdito M euros supone el cobro de un 5% de comisin sobre el importe sacado, si ste es menor que 200 euros y el saldo de la cuenta es negativo. En la capa de objeto del caso de la figura incluye, por ejemplo, una invariante que indica que el saldo de la cuenta debe ser superar siempre al crdito concedido (invariant {balance(self) >= - creditLimit}); una postcondicin sobre el constructor Account que denota que el saldo de una cuenta recin creada es cero (constructor Account() ensure {balance(result) == balance(empty)}), y una precondicin para la operacin credit(M : Money) que expresa que el importe que se saca a crdito debe ser positivo (require { M>0 }). A partir de estas consideraciones, los autores realizan una particin del espacio de estados de la clase, obteniendo estados abstractos por cada trmino booleano de la capa funcional. A partir, por ejemplo, de la propiedad eq balance(empty)=0 podran obtenerse los estados en que la cuenta tiene saldo negativo, saldo cero y saldo positivo. Combinando adems estos estados con la invariante de la capa de objeto (invariant {balance(self) >= - creditLimit}), se podran obtener los siguientes cinco subestados: balance(self) < -creditLimit balance(self) = -creditLimit 0> balance(self) > -creditLimit balance(self) = 0 balance(self) > 0 inalcanzable debido a la invariante

20

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Puesto que el valor de creditLimit es 1000, los estados concretos son los siguientes (ntese la adicin de un estado inicial adicional, en el que el objeto se encuentra antes de ser creado; igualmente podran crearse estados finales si la clase tuviera destructores): S0= { no creado }; S1= { b==1000 }; S2= { -1000<b<0}; S3= { b==0}; S4={ b>0} Obtenidos los estados, se genera el conjunto de transiciones, formadas por una llamada a un mtodo y una posible condicin de guarda, obtenida de las precondiciones del mtodo. De este modo, del anterior conjunto de estados y del ejemplo de la Figura 7 se obtiene la mquina de estados mostrada en la Figura 8.
t0= Account() t1= credit(m) {0 < m < 1000} t2= credit(m) {m == 1000} t3= credit(m) {1000 < m} t4 = credit(m) {0 < m < 1000 and b + m == 0} t5 = credit(m) {(0 < m < 1000 and 0 < b + m) or 1000 = m} t6 = credit(m) {0 < m < 1000 and -1000 < b + m < 0} t7 = credit(m) {0 < m} t8 = credit(m) {0 < m} t9 = debit(m) {1000 < m and b - m == -1000} t10 = debit(m) {0 < m and -1000 < b - m < 0} t11 = debit(m) {0 < m and b - m == 0} t12 = debit(m) {0 < m and 0 < b - m} t13 = debit(m) {0 < m < 1000} t14 = debit(m) {m == 1000} t15 = debit(m) {(200 m < 990 and b - m == -990) or (0 < m < 200 and b - 1.05 * m == -1000)} t16 = debit(m) {(200 =m < 990 and -990 < b - m < 10) or (0 < m < 200 and -1000 < b - 1.05 * m < 0)} t17 = findBalance() t18 = findBalance() t19 = findBalance() t20 = findBalance()

Figura 8. Mquina de estados obtenida, tomada de (Tse and Xu 1996)

La mquina de estaos se procesa para generar secuencias de mtodos que logren diferentes criterios de cobertura, como cobertura de estados, transiciones y caminos. 3.01.3 Mtodo ASTOOT (Doong and Frankl 1994) utilizan especificaciones algebraicas de las clases para la generacin y ejecucin de casos de prueba en su mtodo ASTOOT (A Set of Tools for Object-Oriented Testing). Una especificacin algebraica consta de una parte sintctica y otra semntica: La sintctica incluye los nombres y signatura de las operaciones.

21

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

La semntica incluye una lista de axiomas que describen la relacin entre funciones, utilizndose en muchos casos axiomas de reescritura para esta descripcin. As, dos secuencias de operaciones S1 y S2 son equivalentes si se pueden usar los axiomas como reglas de reescritura para transformar S1 en S2.

La siguiente figura, tomada de (Doong and Frankl 1994), muestra la especificacin algebraica de una cola de prioridad. De acuerdo con esta figura, la secuencia create.add(5).delete(3) es equivalente a la secuencia create.add(5), pues puede aplicarse dos veces el sexto axioma.

Figura 9. Especificacin algebraica de una cola de prioridad, tomada de (Doong and Frankl 1994)

Para estos autores, dos objetos O1 y O2 de clase C son observacionalmente equivalentes si y slo si:

22

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

(1)

C es una clase primitiva (entero, real...), O1 y O2 tienen valores idnticos. C no es una clase primitiva y, para cualquier secuencia S de operaciones de C que devuelven un objeto de clase C, O1.S es observacionalmente equivalente a O2.S como objeto de clase C.

(2)

En otras palabras, cuando es imposible distinguir O1 de O2 usando las operaciones de C. Si se dispusiera de una cantidad de tiempo infinita para comprobar si dos objetos son observacionalmente equivalentes, podra utilizarse el siguiente procedimiento para comprobar la correccin de la clase C: Sea U el conjunto de tuplas (S1, S2, etiqueta), donde S1 y S2 son secuencias de mensajes, y etiqueta es un texto que vale equivalente o no equivalente. Para cada tupla de U, enviar las secuencias S1 y S2 a O1 y O2 y comprobar si ambos objetos son observacionalmente equivalentes. Si todas las equivalencias observacionales se comprueban de acuerdo con las etiquetas, entonces la implementacin de C es correcta, e incorrecta en caso contrario. La equivalencia observacional de dos objetos puede resolverse con un mtodo tipo equals; sin embargo, la finitud del tiempo para realizar las pruebas es irresoluble, por lo que sus autores la han adaptado en la familia de herramientas ASTOOT. El componente de generacin de casos de prueba toma la descripcin sintctica y semntica de la clase que se va a probar (Figura 9) y la traduce a una representacin arborescente. Con esta representacin, lee una secuencia de operaciones suministrada por el usuario y le aplica una serie de transformaciones para obtener secuencias de operaciones equivalentes. Las operaciones incluidas en las secuencias son simblicas, en el sentido de que carecen de parmetros reales. Por ltimo, y teniendo en cuenta la asuncin explicada ms arriba, la comprobacin de la correccin de la clase la realizan pasando valores reales a los parmetros de los mensajes contenidos en las secuencias de cada tupla.

23

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

3.01.4 Obtencin automtica de especificaciones algebraicas (Henkel and Diwan 2003) han desarrollado una herramienta que obtiene de manera automtica especificaciones algebraicas a partir de clases Java. Comienzan obteniendo una lista de secuencias vlidas mediante llamadas sucesivas a los constructores de la clase y a algunos de sus mtodos, pasando valores adecuados a los parmetros de estas operaciones. Si alguna de las secuencias lanza una excepcin, se deshace la ltima operacin o se prueba con un nuevo valor del argumento (Figura 10).

Figura 10. Generacin incremental de trminos aplicada a la clase IntStack (Pila de enteros), tomada de (Henkel and Diwan 2003)

Generadas las secuencias, obtienen ecuaciones de igualdad del estilo de las mostradas en la Figura 7 y en la Figura 9, pero que incluyen valores reales en lugar de simblicos: Ecuaciones de igualdad de secuencias diferentes, como por ejemplo:
pop(push(IntStack().state, 4).state).state=IntStack().state

Ecuaciones de igualdad de secuencias con constantes, como:


pop(push(IntStack().state, 4).state).retval=4

A partir de las ecuaciones se generan los axiomas, que constan de dos secuencias y una serie de variables cuantificadas. As, de la ecuacin de la izquierda, se obtiene el axioma de la derecha:
IntAdd(size(IntStack().state).retval,1).retval = size(push(IntStack().state, 3).state).retval s:IntStack, i:int IntAdd(size(s).retval,1).retval = size(push(s, I).state).retval

24

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Figura 11. Ejemplo de obtencin de un axioma a partir de una ecuacin

Muchos de los axiomas generados son redundantes, por lo que con posterioridad se detectan y se eliminan aplicando reglas de reescritura, para lo que primero deben identificarse stas de entre el conjunto de axiomas. Se considera que un axioma es una regla de reescritura si: (1) el lado izquierdo y el derecho tienen diferente longitud; y (2) las variables libres que aparecen en lado ms corto son un subconjunto de las variables libres que aparecen en el lado derecho.

3.02 Pruebas a partir de modelos


3.02.1 Diagramas de clases UML (Baudry, Traon et al. 2002) analizan la complejidad de diagramas de clases UML con respecto a su facilidad de prueba, con el objetivo de proponer una serie de guas de diseo que permitan disear sistemas orientados a objeto fciles de probar o, al menos, probables en tiempo finito. El estudio se basa fundamentalmente en medidas de acoplamiento, que viene a ser el grado en que unos elementos dependen de otros; as, se asume que a mayor acoplamiento (tanto directo como indirecto), mayor dificultad para probar el diseo. As, los autores dan las siguientes definiciones: Relacin de uso directa: la clase A usa la clase B cuando existe una asociacin desde A hacia B, o bien cuando hay una dependencia con el estereotipo <<usa>> desde A hacia B. Este conjunto de relaciones se llama SDU (Set of Direct Usage relationship). Ntese que una asociacin no dirigida representa realmente dos relaciones de este conjunto. Relacin de uso transitiva: es el conjunto formado por la clausura transitiva de SDU. Relacin de uso transitiva real: si existe una relacin transitiva entre las clases A, B y, adems, el cdigo fuente obtenido del diagrama de clases permite la interaccin entre dos instancias de A y de B, entonces se dice que dicha relacin transitiva es real. Interaccin de clases (interaccin potencial): siendo A, B dos clases, ocurre si y slo si A Ri B y B Ri A, siendo i distinto de j. [La interaccin es poten-

25

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

cial porque tal vez no llegue fsicamente a producirse en la ejecucin del sistema]. Interaccin entre objetos (interaccin real): siendo A, B dos clases, ocurre si y slo si (1) A Ri B y B Ri A, siendo i distinto de j, y (2) Ri y Rj son relaciones transitivas reales. [La interaccin es real porque se produce la interaccin entre ambos objetos en la ejecucin del sistema obtenido del diseo]. El criterio de prueba propuesto es el siguiente: para cada interaccin entre clases, o bien se obtiene un caso que prueba la interaccin entre objetos, o bien se obtiene un informe mostrando que tal interaccin no es factible. Puesto que la tarea de producir casos de prueba o informes es imposible si el nmero de interacciones es muy alto, es preciso obtener diseos que disminuyan el nmero de interacciones, de modo que se haga factible as la prueba completa del diseo de clases. Antes de someterlo al criterio de pruebas, el diseo de clases debe ser evaluado para conocer el nmero de interacciones entre clases, modificndolo si es muy alto y tal mejora es posible, o rechazndolo directamente en otro caso. La mejora del diseo puede lograrse reduciendo el acoplamiento o anotndolo con restricciones que eviten la codificacin de interacciones entre objetos propensas a error. Los autores proponen la anotacin utilizando los estereotipos <<create>> (para indicar que la clase A crea instancias de la clase B), <<use_consult>> (para indicar que la clase A slo utiliza mtodos tipo get de B) y <<use_def>> (para indicar que la clase A modifica el estado de las instancias de B). Estos estereotipos se utilizan en el proceso de construccin del Grafo de Dependencias de Clases (en ingls Class Dependency Graph, o CDG), que representa las relaciones transitivas entre clases junto a las relaciones de herencia e implementacin. La siguiente figura muestra algunos ejemplos sobre la obtencin del CDG, en la que aparecen algunas etiquetas aadidas a los nodos del CDG para representar el tipo de relacin existente.

26

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Figura 12. Algunos ejemplos de obtencin del CDG, tomada de (Baudry, Traon et al. 2002)

A partir del CDG pueden calcularse medidas como la complejidad de una interaccin, definida en funcin de la complejidad de los diferentes caminos por los que puede irse desde un objeto hasta otro:

complejidad (CI ) =

nbPaths i =1

((complejidad ( P ) complejidad ( P ))
i j >i j

Ecuacin 1. Complejidad de una interaccin

La complejidad de un camino en una interaccin es necesaria para calcular el valor de la Ecuacin 1, y se define como el productorio de la complejidad asociada a cada jerarqua cruzada por la interaccin (parmetro IH):
complejidad ( P) =
nbCrossed i =1

complejidad ( IH , P)

Ecuacin 2. Complejidad de un camino en una interaccin

Obviamente, es preciso poder calcular la complejidad de un camino que pasa por una jerarqua de herencia:
complejidad ( IH , P) =
nbDP i =1

complejidad (dp )
i

Ecuacin 3. Complejidad de un camino que pasa por una jerarqua de herencia

Por ltimo, la complejidad de un camino de descendientes es el nmero de interacciones potenciales entre las clases que hay en ese camino. El caso peor se dara cuando todas las clases estuvieran relacionadas con todas las clases, lo que supone un valor mximo de n(n-1). De manera general, la com-

27

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

plejidad de un camino se corresponde con la Ecuacin 4, en donde h representa la altura del camino:
comlejidad (dp ) = h (h 1)
Ecuacin 4. Complejidad de un camino de descendientes

En la siguiente figura, tomada de (Baudry, Traon et al. 2002), la complejidad del camino que va desde client hasta b1 pasando por la relacin de herencia de la clase d es 1+3*(3-1)+1: 1 por la relacin de uso de client con respecto a d; 3*(3-1) por el camino de descendientes de la jerarqua d, y otra vez 1 por la relacin de uso desde d22 a b1.

Ecuacin 5. Ejemplo para el clculo

3.02.2 Criterios de cobertura de pruebas para diseos UML (Andrews, France et al. 2003) proponen varios criterios de cobertura para las pruebas de diferentes diagramas UML. Para diagramas de clases, proponen los siguientes: AEM (Association-end multiplicity): dado un conjunto de pruebas T y un modelo SM, T debe causar que se cree cada par de multiplicidades representativo en las asociaciones de SM. As, si existe una asociacin cuya multiplicidad es, en un extremo, p..n, debera instanciarse la asociacin con p elementos (valor mnimo), n elementos (valor mximo) y con uno o ms valores en el intervalo (p+1, n-1). GN (Generalization): dado un conjunto de pruebas T y un modelo SM, T debe conseguir que se cree cada relacin de generalizacin de SM. CA (Class attribute): dado un conjunto de pruebas T, un modelo SM y una clase C, T debe conseguir que se creen conjuntos de valores representativos de los diferentes atributos de la clase C. El conjunto de

28

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

valores representativos se consigue en tres pasos: (1) crear valores representativos para cada atributo, para lo que pueden usarse clases de equivalencia; (2) calcular el producto cartesiano de estos valores; (3) eliminar los conjuntos de valores invlidos, considerando el dominio del problema, posibles restricciones que anoten el diagrama, etc. Para diagramas de interaccin, los criterios propuestos son: Cobertura de condiciones: dado un conjunto de casos de prueba T y un diagrama de interaccin D, T debe conseguir que cada condicin del diagrama se evale a true y a false. Cobertura completa de predicados (FP: full predicate coverage): cada clusula de cada condicin debe evaluarse a true y a false. Cobertura de mensajes (EML: each message on link): cada mensaje del diagrama debe ejecutarse al menos una vez. Cobertura de caminos (AMP: all message paths): todos los posibles caminos de ejecucin deben ejecutarse. Cobertura de colecciones (Coll: Collection coverage): el conjunto de casos de prueba debe probar cada interaccin con colecciones al menos una vez. 3.02.3 Diagramas de estados (Burton, Clark et al. 2001; Hong, Lee et al. 2001) 3.02.4 En otros diagramas (Basanieri, Bertolino et al. 2002) utilizan diagramas de casos de uso y de secuencia para derivar casos de prueba desde las etapas iniciales del desarrollo de un sistema orientado a objetos. Tras realizar una serie de anlisis y adaptaciones de los diagramas, aplican los siguientes pasos: Definir el conjunto de secuencias de mensajes MS a partir de los diagramas de secuencia. Cada secuencia comienza con un mensaje m sin predecesor (habitualmente, un mensaje enviado al sistema por un actor) y el conjunto de mensajes cuya ejecucin dispara m (aquellos cuyo inicio est en el foco de control en que termina m).

29

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Analizar de subcasos, que bsicamente consiste en construir varias secuencias a partir de las posibles instrucciones condicionales que anotan los diagramas de secuencia.

Identificar de los conjuntos de valores de prueba, que se construyen a partir de los tipos de los parmetros de los mtodos y del anlisis de los diagramas de clases del sistema.

Seleccionar, para cada mensaje de la secuencia, las situaciones relevantes en que el mensaje puede ocurrir y, para cada valor de prueba, valores vlidos que puedan incluirse en el mensaje.

Eliminar valores contradictorios o poco significativos, para lo que los autores sugieren utilizar clases de equivalencia.

Obtener procedimientos de prueba, que puede hacerse automticamente con los datos obtenidos en los pasos anteriores.

As, a partir del diagrama de secuencia mostrado en la Figura 13, se identifican las siguientes secuencias de mensajes:
MS_1: 1.start(), 1.1.open() MS_2: 2.enterUserName(String) MS_3: 3.enterPassword(String) MS_4: 4.loginUser(), 4.1.validateuserIDPassword(String, String) 4.2.setupSecurityContext(), 4.2.1.new UserID() 4.3.closeLoginSelection()

30

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Figura 13. Diagrama de secuencia de ejemplo, tomado de (Basanieri, Bertolino et al. 2002)

El diagrama incluye sin embargo una instruccin condicional, por lo que la secuencia MS_4 puede dividirse en dos:
MS_4.1: 4.loginUser(), 4.1.validateuserIDPassword(String, String) 4.2.setupSecurityContext(), 4.2.1.new UserID() MS_4.2: 4.loginUser(), 4.1.validateuserIDPassword(String, String) 4.3.closeLoginSelection()

3.03 Pruebas de componentes


3.03.1 Uso de BIT wrappers (Edwards 2001) propone la utilizacin de BIT wrappers (Built-In-Test wrappers, o adaptadores construidos durante las pruebas) para la prueba de componentes. Esencialmente, un BIT wrapper es una clase que ofrece la misma interfaz que el componente para el que se ha construido. En la fase de pruebas

31

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

del componente, se ejecutan las operaciones de ste a travs del BIT wrapper, que posee funcionalidades como la comprobacin de las precondiciones de la operacin antes de llamar a la operacin real, y la comprobacin de las postcondiciones tras su ejecucin. Adems, el BIT wrapper puede mantenerse para que capture las llamadas que los clientes hacen a las operaciones del componente (Figura 14).

Figura 14. Ubicacin del BIT wrapper alrededor del componente. Figura tomada de (Edwards 2001)

Algunas caractersticas de los BIT wrappers son las siguientes: Son transparentes al componente y a los posibles clientes. La adicin o supresin de BIT wrappers slo requiere la modificacin de las declaraciones en el cdigo de los clientes. Se aaden nuevas capacidades de comprobacin de restricciones a las que ya realiza el propio componente. La violacin de las restricciones se detectan en el momento en que ocurren, de manera que se evita su propagacin a otros componentes. Si se posee una especificacin formal del componente, el BIT wrapper se puede generar automticamente.

32

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Para la fase de pruebas del componente, (Edwards 2001) propone el proceso que se muestra esquemticamente en la Figura 15: el conjunto de casos de prueba contenido en el Test suite (que se ha podido generar automticamente) se pasa a un ejecutor de pruebas (Test driver), que prueba el componente a travs del BIT wrapper. El resultado es, por un lado, los resultados obtenidos de la ejecucin de cada caso de prueba y, por otro, un informe con los errores encontrados.

Figura 15. Proceso de pruebas con BIT wappers

Tanto el BIT wrapper como el Test driver pueden generarse automticamente: para el primero es preciso disponer de una descripcin formal del componente (el autor utiliza el lenguaje Resolve, aunque podra emplearse cualquier otro); para la generacin del segundo podran usarse generadores aleatorios, de valores lmite, etc. 3.03.2 Mutacin de interfaces (Ghosh and Mathur 2001) proponen aplicar ciertos operadores de mutacin a las interfaces de componentes para la realizacin de pruebas, as como ciertos criterios de cobertura para validar las pruebas realizadas. Los autores proponen los siguientes operadores de mutacin para CORBAIDL son los siguientes: 33

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Reemplazar inout por out. Reemplazar out por inout. Intercambiar parmetros de tipos compatibles. Jugar con un parmetro (operador twiddle): por ejemplo, sumarle uno si es entero, aadirle un carcter si es una cadena, etc.

Poner a cero los valores numricos. Sustituir por null.

Los criterios de cobertura que proponen son los siguientes: Cobertura de llamadas a mtodos de la interfaz del componente. Cobertura de excepciones lanzadas por la interfaz del componente. Cobertura de llamadas a mtodos y de excepciones lanzadas.

La mutacin se consigue sustituyendo la interfaz por una nueva versin, como muestra esta figura:
Cliente Interfaz

Servidor

Cliente

Interfaz mutada

Servidor

Figura 16. Mutacin de interfaces

4. RESULTADOS EXPERIMENTALES
(Juristo, Moreno et al. 2002) han analizado los resultados experimentales de diferentes tcnicas de prueba extradas de la literatura, de acuerdo con la siguiente clasificacin: Familia de tcnicas aleatorias, en las que los casos de prueba son generados aleatoriamente, sin seguir ninguna pauta preestablecida. Familia de tcnicas funcionales, que utilizan la especificacin del programa para generar casos de prueba de caja negra. Familia de tcnicas de flujo de control, que requieren el conocimiento del cdigo fuente para seleccionar una serie de caminos a lo largo del programa, de modo que se ejecute su modelo de control. 34

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

Familia de tcnicas de flujo de datos, que requieren tambin el conocimiento del cdigo fuente para seleccionar secuencias de eventos relacionados con el estado de los datos.

Familia de tcnicas de mutacin, que modelan mediante operadores de mutacin los errores tpicos que se cometen al hacer un programa, y lo ejecutan mediante casos de prueba que detecten dichos errores.

Los resultados de cada familia los ubican en una de las tres siguientes categoras: (1) Nivel 1: afirmaciones no contrastadas de manera empricamente formal. (2) Nivel 2: afirmaciones contrastadas empricamente pero no con situaciones reales; es decir, con programas no reales o con fallos lo reales. (3) Nivel 3: afirmaciones contrastadas empricamente en situaciones reales. Respecto de la Familia de tcnicas de flujo de datos, las autoras analizan dos trabajos que sitan a esta familia en los niveles 2 y 3. Respecto de la Familia de tcnicas de mutacin, se analizan tres trabajos que sitan a esta familia en nivel 2. Igualmente, realizan un estudio comparativo entre las familias de flujo de datos, flujo de control y aleatoria. Las autoras afirman que, ante restricciones de tiempo se pueden usar tcnicas aleatorias confiando en que en el 50% de los casos nos dar una efectividad similar a la de all-uses y all-edges [...]. Si se necesita un testing exhaustivo, entonces se puede asegurar aplicando alluses. No obstante, esta afirmacin la sustentan a nivel 2 y no a nivel 3. Tambin comparan la familia de mutacin y la de flujo de datos, indicando que si se busca conseguir cobertura alta y no se dispone de mucho tiempo, es preferible usar all-uses frente a mutacin, ya que en aproximadamente la mitad de los casos ser igual de efectiva que la mutacin, sustentando esta afirmacin en un nivel 2. Comparan tambin la familia funcional con la de flujo de control, lo que viene a significar una comparacin entre pruebas de caja negra y de caja blanca. Afirman que, si se est trabajando con sujetos con experiencia, en caso de disponer de tiempo suficiente, es mejor utilizar la tcnica de anlisis de valores lmite frente a cobertura de sentencias ya que se encontrarn ms fallos, aun-

35

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

que les llevar ms tiempo. Por el contrario, si se est trabajando con sujetos sin experiencia y no se tiene tiempo, es mejor usar cobertura de sentencias. Otras conclusiones son que es preferible usar anlisis de valores lmite frente a cobertura de condicin. Todas estas conclusiones se encuentran a nivel 2. De manera general, las autoras destacan la ubicacin en nivel 2 de la mayora de las tcnicas, lo que indica que hay an mucha investigacin que realizar.

5. REFERENCIAS
Andrews, A., R. France, et al. (2003). "Test adequacy criteria for UML design models." Software Testing, Verification and Reliability(13): 95-127. Basanieri, F., A. Bertolino, et al. (2002). The Cow_Suite Approach to Planning and Deriving Test Suites in UML Projects. 5th International Conference on The Unified Modeling Language, Springer-Verlag. LNCS. Bashir, I. and A. L. Goel (2000). Testing Object-Oriented Software. Life Cycle Solutions. New-York, Springer-Verlag. Baudry, B., Y. L. Traon, et al. (2002). Testability Analysis of a UML Class Diagram. 8th IEEE Symposium on Software Metrics. Burton, S., J. Clark, et al. (2001). Automatic generation of tests from statecharts specifications. Formal Approaches to Testing of Software, Aalborg, Denmark, BRICS. Cornett, S. (2002). Code Coverage Analysis. Daz, E., J. Tuya, et al. (2003). Pruebas automticas de cobertura de software mediante una herramienta basada en Bsqueda Tab. VIII Jornadas de Ingeniera del Software y Bases de Datos, Alicante, Spain. Doong, R. K. and P. G. Frankl (1994). "The ASTOOT approach to testing object-oriented programs." ACM Transactions on Software Engineering and Methodology 3(2): 101-130. Edwards, S. H. (2001). "A framework for practical, automated black-box testing of component-based software." Software Testing, Verification and Reliability(11): 97-111. Edwards, S. H. (2001). "A framework for practiucal, automated black-box testing of component-based software." Software Testing, Verification and Reliability(11): 97-111. Fox, C. (1998). Java Code Inspection Checklist. Ghosh, S. and A. P. Mathur (2001). "Interface mutation." Software Testing, Verification and Reliability(11): 227-247. Henkel, J. and A. Diwan (2003). Discovering Algebraic Specifications from Java Classes. 17th European Conference on Object-Oriented Programming (ECOOP), Springer. Hong, H. S., I. Lee, et al. (2001). Automatic test generation from statecharts using model checking. Formal Approaches to Testing of Software, Aalborg, Denmark, BRICS.

36

Mantenimiento Avanzado de Sistemas de Informacin Pruebas del software

ISO/IEC (1995). ISO/IEC 12207. International Standard. Software Life Cycle Processes. Geneve, International Standard Organziation/International Electrotechnical Committee. Juristo, N., A. M. Moreno, et al. (2002). A Survey on Testing Technique Empirical Studies: How Limited is our Knowledge. International Symposium on Empirical Software Engineering (ISESE'02), Nara, Japan. Kim, S., J. A. Clark, et al. (2000). Class Mutation: Mutation Testing for ObjectOriented Programs. International Conference on Object-Oriented and Internet-based Technologies, Concepts, and Applications for a Networked World, Net.ObjectDays'2000, Germany. Kirani, S. and W. T. Tsai (1994). "Method sequence specification and verification of classes." Journal of Object-Oriented Programming 7(6): 28-38. Lapierre, S., E. Merlo, et al. (1999). Automatic Unit Test Data Generation Using Mixed-Integer Linear Programming and Execution Trees. International Conference on Software Maintenance, Oxford, England. Michael, McGaw, et al. (2001). "Generating Software Test Data by Evolution." IEEE Transactions on Software Engineering 27(12): 1085-1110. Offut, A. J. (1995). A practical system for mutation testing: help for the common programmer. 12th International Conference on Testing Computer Software. Offut, A. J., G. Rothermel, et al. (1996). "An experimental determination of sufficient mutant operators." ACM Transactions on Software Engineering and Methodology 5(2): 99-118. Pargas, R. P., M. J. Harrold, et al. (1999). "Test-Data Generation Using Genetic Algorithms." Software Testing, Verification and Reliability(9): 263-282. Rice, R. W. (2002). "Surviving the top 10 challenges of software test automation." CrossTalk: The Journal of Defense Software Engineering(Mayo): 26-29. Tracey, N., J. Clark, et al. (1998). Automated program flaw finding using simulated annealing. International Symposium on Software Testing and Analysis, Clearwater Beach, Florida, USA, ACM/SIGSOFT. Tse, T. and Z. Xu (1996). Test Case Generation for Class-Level ObjectOriented Testing. 9th International Software Quality Week, San Francisco, CA.

37

También podría gustarte