Upload
vuongdat
View
222
Download
0
Embed Size (px)
Citation preview
Prueba de programas
• Proceso de ejecución y evaluación, manual o automática, de un sistema informático, con los siguientes objetivos:
– Eliminación de los errores de especificación, diseño e implementación
2
e implementación
– Verificación de los requisitos funcionales (qué funcionalidad falta? es lo que el usuario quería?)
– Verificación de los requisitos no funcionales
• Coste: hasta el 50% del tiempo!
Prueba de programas
Configuración
Software a
probar
Depuración
Software
CorregidoResultados Evaluación Errores
Correcciones
3
PruebaDepuración
Configuración
Prueba
(Juegos Pruebas)
Modelo
De
Fiabilidad
Tasa error
Predicción
Fiabilidad
Prueba de programas
• Detección vs. Corrección (+ localización)
• Detección -> Métodos: – Verificación formal (proving)– Pruebas (testing)
4
– Pruebas (testing)
“Program testing can be used to show the presence of bugs, but never to show their absence” – Dijkstra
"Be careful about using the following code -- I've only proven that it works, I haven't tested it." – Knuth
“Test your software or your users will” - Hunt & Thomas
Verificación formal
• Demostración formal de que el programa satisface la especificación
Obstáculos: • Técnicas complejas. Personal cualificado• No garantiza la ausencia de errores de especificación
5
• No garantiza la ausencia de errores de especificación• Raramente se dispone de una especificación formal
del resto de componentes del sistema (p.ej., librerías, entrada/salida, …)
• Uso en fragmentos críticos del programa y/o en paralelo con el diseño
Pruebas
Estado entrada
Programa(transformador de
Ideal: Batería de ejecuciones para probar todos los estados de entrada
Impracticable!
6
(transformador de estados)
Estado salida
Testing: Escoger un subconjunto representativo de todos los estados
Impracticable!
Pruebas (2)
• Técnica más barata y más usada– habilidad programador– sistemática
• No garantiza la ausencia de errores de
7
• No garantiza la ausencia de errores de– especificación– diseño – implementación
• Se puede hacer más o menos exhaustiva, según la importancia asignada a la fiabilidad
Seguimiento manual
Prueba sistemática
Pruebas (3)
Nombres:• Test case (una prueba)• Test suite (un juego de pruebas)• Test plan (una colección de juegos de pruebas)• Scenario test (una tarea que querría realizar un
8
• Scenario test (una tarea que querría realizar un usuario hipotético)
Tarea: Diseñar los anteriores para cubrir todas (???) las posibilidades de ejecuciónEntradas: Ficheros, BDs, valores parámetros/ctes., valores a
introducir interactivamente, …Predefinir también las salidas!
Prueba de programas
Niveles:
• Pruebas de componentes
• Pruebas de integración
• Pruebas de sistema
9
• Pruebas de sistema
• Test de aceptación
Pruebas de componentes
En O.O.: componente clase
Técnicas:
• De caja blanca– Estructura interna
10
– Estructura interna
• De caja negra– funcionalidad
Pruebas de componentes: Caja blanca
• Necesario el acceso al código del componente• Batería para provocar la ejecución, al menos
una vez, de cada instrucción del programaOpciones: cada rama del “if” se ha de ejecutarBucles: ejecutar casos límite (ejecutar el bucle o no)
e interior
11
e interiorEstructuras de datos: internamente (prueba
completa según su casuística)
• Más general: cada posible camino. • Más general: cada camino con diferentes
valores
Pruebas de componentes: Caja blanca (2)
{
s1;
while (c1) {
if (c2) s2 else s3;
s4;
s6
inici s1
c1
c2
s5
c3
12
s4;
}
if (c3) s5 else s6;
}
Método basis set :1) Escoger un conjunto de caminos que cubren
todos los arcos
2) Poner un test case para cada camino
s2 s3
s4 final
Pruebas de componentes: Caja blanca (3)
Método dataflow:• Localizar qué puntos en el programa dan valor a una
variable y cuáles la consumen
• Para cada variable x definir conjuntos de instrucciones Def(x) (donde se asigna) y Use(x)
13
instrucciones Def(x) (donde se asigna) y Use(x) (donde se lee)
• Para cada instrucción s, definir Def(s) y Use(s) a partir de los Def(x) y Use(x)
• Definir cadenas DU (Def-Use):
(x,s1,s2) si x está en Def(s1) y en Use(s2) y
la definición de x en s1 aún es válida en s2
• Necesario cubrir al menos una vez cada cadena DU
Pruebas de componentes: Caja negra• Complementario y normalmente posterior a caja blanca• Se usa sólo la interficie del componente• Tipos error:
– funcionalidades incorrectas o no previstas– errores de interficie– errores de E.D. externas– errores de funcionamiento– errores de inicialización o terminación
14
– errores de inicialización o terminación• Juegos de prueba mínimamente completos:
– Dividir el dominio de cada variable en “clases de equivalencia” (comportamiento uniforme - subjetivo…)Ej: x Є N
– Escoger un representante de cada clase– Test suite: todas las combinaciones de representantes (conjunto
cociente)• Atención a los casos extremos / valores frontera
{0}
{x | 0 < x < 7}
{x | x ≥ 7}
Concurrencia / tiempo real
Necesario comprobar, además:• Secuenciación temporal (timing) de los datos• Paralelismo / interacción entre procesos• Problemas de bloqueo y competencia entre procesos/recursos• Reacción ante eventos externos/ relación con el entorno de
ejecución• Reparto de carga
15
• Reparto de carga• Recuperación de errores (hardware, otros programas, ...)
• Sistemas operativos, sistemas de fabricación, redes, …• Código de control de errores llega a ser el 70%
Estrategia de prueba
Etapas:
• Planificación prueba: orden de prueba de las piezas
• Diseño: casos a probar y resultados esperados
• Prueba: ejecución
• Obtención de resultados
16
• Obtención de resultados
• Evaluación
Pruebas de integración
• Se prueban interacciones entre componentesA nivel de test: comp. no probado <-> comp. no construido
• Integración incremental: No “Big Bang”• También “caja blanca + caja negra”• Enfoques:
– Ascendente: Drivers
17
– Ascendente: DriversPrograma que prueba un componente de “nivel más bajo”
– Descendente: StubsPrograma que permite probar otro “de nivel más alto”
(Los niveles vienen marcados por los distintos tipos de relaciones entre componentes utilizadas)
Pruebas de integración: Drivers
Driver
Leer datos de test
Invocar Retornar
Presentarresultados
Atención:
Se piden drivers interactivos!!
Que no haga falta
18
Clase a probar
Invocar métodos
Retornar resultados
Que no haga falta recompilar para probar con nuevos datos!
Entrada por teclado o ficheros de texto plano!
Pruebas de integración: Stubs
Clasea probar
Invocar Retornar
Stub: representa una clase C con interficie conocida pero aún no ejecutable
Implementa una versión simple de la funcionalidad final de C
19
Stub
Invocar métodos
Retornar resultados
funcionalidad final de C
P.ej.
• Escribir “se ha llamado el método m de C con parámetros x”
• Retornar datos constantes• ...
Caso particular: Clases abstractas
C: Clase abstracta El stub concreto implementa los
métodos abstractos de C de manera simple.
20
simple.
Permite crear instancias de C para probar los métodos implementados en C (eventualmente por medio de otros stubs y drivers)
Stubconcreto
Pruebas de integración
• Enfoques:– Ascendente: Drivers
-) El programa no existe hasta el final+) Los componentes de nivel más bajo pasan más pruebas
– Descendente (profundidad/anchura): Stubs -) Construcción de stubs+) Ya tenemos el programa entero – solapamiento con pruebas
21
+) Ya tenemos el programa entero – solapamiento con pruebas de validación
– Métodos híbridos: Sandwich TestingSi conviene comenzar probando los componentes más críticos:• Reutilización• Visibilidad del producto• Grado de acoplamiento y uso de los distintos componentes• Adquisición de datos a partir del usuario
Pruebas de integración
• Stubs, drivers y test suites son el soporte (scaffolding) para construir nuestro sistema
• Serán retirados al final
22
• Pero pasar tiempo diseñándolos NO es tiempo perdido
• Escribe mucho más código que el que irá en la versión final
Pruebas
Consejos:
• Prueba pronto: ahorrarás tiempo y €
• Escribe tests que prueben propiedades bien definidas
23
definidas
• Escribe tests que se entiendan
• Documenta los tests (formulario!)
• Uso de herramientas: JUnit
• Escribe los tests antes que el código
• Escribe mucho código para hacer testing
Descripció dels jocs de provesCada fitxer executable del segon lliurament ha d’anar acompanyat d’un text
que descrigui:
•Objecte de la prova: casos d'ús i classes, o integració de conjunts, provats
anteriorment, que es proven
•Altres elements integrats a la prova: classes ja provades o que s'han
provat d'alguna altra manera –reutilitzats, etc.– integrades en aquest
executable (si n'hi ha)
•Drivers construïts per aquesta prova i integrats en l'executable, amb
descripció de la seva missió (si n'hi ha)
•Stubs construïts per aquesta prova i integrats en l'executable, amb
descripció de la seva missió (si n'hi ha)
24
descripció de la seva missió (si n'hi ha)
•Fitxers de dades necessaris: nom dels fitxers de dades, si n'hi ha, i tal cas
les classes que s'emmagatzemen en cadascun
•Valors estudiats: amb quins valors es prova i quina missió tenen, aquí és
on s'hauria de parlar de caixa blanca o negra, conjunts de dades de
comportament homogeni, etc.
•Efectes estudiats: funcionalitats com ara vistes, moviments per la pantalla,
selecció en llistes, etc. que no són dades concretes
•Operativa: petit manual o descripció del funcionament de l'executable, molt
bàsica
Regresión
• Partes que funcionaban dejan de funcionar– Cuando añadimos funcionalidad
– Cuando rediseñamos (“mejoramos”) una parte
• Bugs supuestamente eliminados reaparecen
25
• Bugs supuestamente eliminados reaparecen (regression bugs)
• Especialmente, en tareas de mantenimiento
Regresión (2)
• Test de regresión: Ejecutar todas las baterías ya superadas en etapas anteriores cuando introducimos cambios
• … en cada “build”, o cada noche/semana
26
• Importante: añadir test cases para cada bug ya eliminado!
• Herramientas semi-automáticas para testing (Junit, …)
Junit (1)
• Conjunto de bibliotecas creadas por Erich Gamma y Kent Beckque son utilizadas en programación para hacer pruebas unitariasde aplicaciones Java. (wikipedia)
• JUnit es un conjunto de clases (framework) que permite realizar la ejecución de clases Java de manera controlada, para poder
27
la ejecución de clases Java de manera controlada, para poder evaluar si el funcionamiento de cada uno de los métodos de la clase se comporta como se espera. Es decir, en función de algún valor de entrada se evalúa el valor de retorno esperado; si la clase cumple con la especificación, entonces JUnit devolverá que el método de la clase pasó exitosamente la prueba; en caso de que el valor esperado sea diferente al que regresó el método durante la ejecución, JUnit devolverá un fallo en el método correspondiente.
JUnit (2)
• JUnit es también un medio de controlar las pruebas de regresión, necesarias cuando una parte del código ha sido modificado y se desea ver que el nuevo código cumple con los requerimientos anteriores y que no se ha alterado su funcionalidad después de la nueva modificación.
• El propio framework incluye formas de ver los resultados
28
• El propio framework incluye formas de ver los resultados (runners) que pueden ser en modo texto, gráfico (AWT o Swing) o como tarea en Ant.
• En la actualidad las herramientas de desarrollo como NetBeans y Eclipse cuentan con plug-ins que permiten que la generación de las plantillas necesarias para la creación de las pruebas de una clase Java se realice de manera automática, facilitando al programador enfocarse en la prueba y el resultado esperado, y dejando a la herramienta la creación de las clases que permiten coordinar las pruebas.
Pruebas de validación/ de sistema
Instrumentos• Producto completo• Especificación de requerimientos funcionales y
operativos• Documentación de usuarioPruebas de sistema (entorno real):
29
Pruebas de sistema (entorno real):• Seguridad• Recuperación (caída de sistema)• Potencia (condiciones extremas: volumen, frecuencia,
horas punta, número de usuarios)• Eficiencia (tiempo de respuesta, consumo recursos, …)• Interacción con otro software• Usabilidad…
Test de aceptación
• Realizado por el cliente/usuario final
• Pruebas de aceptación controladas: – alfa: con presencia del programador
– beta: sin presencia del programador
30
– beta: sin presencia del programador
Hasta cuándo probar?• Hasta que se acaba el tiempo o el dinero!
• Cuando #errores detectados/unidad de tiempo tiende a 0
• Producto final = Versión pre-alfa del siguiente producto
Depuración de errores (debugging)
Etapas para cada error:
• Detección (síntomas)
• Localización (causas)
• Determinación de la fase en que se ha producido (especificación-diseño-implementación)
31
(especificación-diseño-implementación)
• Evaluación de la gravedad (leve-grave-crítico) y del coste de corrección
• Corrección
• Comprobación (-> tests de regresión)
Depuración de errores (debugging) (2)
Algunas heurísticas:
• Brute Force Approach: Seguimiento sistemático del funcionamiento del programa
• Backtracking: Retroceder desde el punto donde se ha detectado el síntoma. Problema: efecto lateral?
32
ha detectado el síntoma. Problema: efecto lateral?
• Localizar puntos del programa donde se pudieron producir las causas del síntoma: Mirar variables que intervienen y asignaciones de éstas
• Comprobación de los contratos de las llamadas
(pre y postcondiciones)
• Assert de Java / librería InOut de PRAP
• Regresión: arreglar un bug ha generado otros?
Java – Assert statement
assert Expresión_booleana
assert Expresión_booleana: Expresion_textual
AssertionError [“ “+Expresion_textual]• Las aserciones se usan para afirmar o comprobar
suposiciones sobre el estado del programa que
33
suposiciones sobre el estado del programa que asumimos ciertas: situaciones imposibles, precondiciones, invariantes, postcondiciones,...
• Su checking se puede habilitar/deshabilitar (de forma selectiva o no para clases/packages).
• En principio se usan durante el desarrollo y se deshabilitan durante la explotación
• OJO con efectos laterales de Expresion_booleana
Experiencia
Consejo: • Un error ha de servir para evitar repetirlo• Reflexionad: por qué he cometido este error?• Compartidlo con el resto del grupo!
34
“Experience is the name everyone gives to his mistakes” -Oscar Wilde, Lady Windemere's Fan
“Human beings, who are almost unique in having the ability to learn from the experience of others, are also remarkable for their apparent disinclination to do so” -Douglas Adams, Last Chance to See
“Experience is what you get when you don’t get what you want” - Dan Stanford
ExcepcionesPublic boolean leeDatos (File fichero) throws ExcepFichero1, IOException,…{ …if (linea==null) throw new ExcepFichero1(fichero.getName());…}
Public class ExcepFichero1 extends Exception{public string filename;public ExcepFichero1 (string nombre)
35
public ExcepFichero1 (string nombre){super(“Error en fichero” + nombre + “, formato incorrecto”);filename= nombre;
}}
Al invocar un método con excepciones en su “throws” puedes:• Capturar (Catch) la excepción y gestionarla• Capturar la excepción y mapearla en una de tus excepciones• Declarar la excepción en tu “throws” y pasarla (pila de llamadas)
Excepciones
• Gestionan condiciones inusuales/inesperadas durante la ejecución:– Problemas de estado interno de un objeto (valores de variables
inconsistentes, …)– Errores en manipulación de objetos o datos (ficheros, direcciones de
red, …)– Violación de contrato básico del objeto (leer datos de una stream ya
cerrada, …) • Forma limpia de chequear errores sin llenar el flujo de código con
36
cerrada, …) • Forma limpia de chequear errores sin llenar el flujo de código con
chequeos.• Hacen que las condiciones de error que un método puede señalar
sean parte explícita de la cabecera de ese método (su contrato).• La lista de excepciones puede ser:
– vista por el programador– chequeada por el compilador– preservada por las clases que heredan y redefinen el método
(compatible: lanzar las mismas excepciones o menos, nunca más, ni nuevos tipos, ni más generales que en la superclase)