Prueba de programas - prop/provaprogrames08.pdf · • Test plan (una colección de juegos de...

36
Prueba de programas Projecte de Programació (PROP)

Transcript of Prueba de programas - prop/provaprogrames08.pdf · • Test plan (una colección de juegos de...

Prueba de programas

Projecte de Programació (PROP)

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)