Anda di halaman 1dari 24

•03/06/2010

Programación II

Introducción a las Pruebas de


Programas
Ángel Lucas González
Jaime Ramírez
Guillermo Román
DLSIIS. Facultad de Informática
Universidad Politécnica de Madrid

Definiciones(I)
• VERIFICAR: Comprobar que el sistema cumple
fielmente con lo especificado
• VALIDAR: Comprobar que no hay errores
• ERROR: Incorrección dentro de un módulo
software que conduce a un resultado incorrecto
• FALLO: Es la manifestación de un error en el
software
ft
• DEFECTO: Es una desviación en el valor
esperado para una cierta característica
2

•1
•03/06/2010

Definiciones(II)
• PRUEBA: Proceso en el que se ejecuta un
sistema con el objetivo de detectar fallos
• DEPURACIÓN: Es el proceso en el que se
localiza el error que es la causa de un fallo, se
determina la forma de corregirlo, se evalúa el
efecto de la corrección y se lleva a cabo la
corrección.
corrección
– Después del proceso de depuración HAY QUE
REPETIR LAS PRUEBAS

Objetivo
• Realizar un barrido exhaustivo de todo el código es
impracticable por el coste que supone
• El coste de detectar un error suele ser mayor que el
de corrección
• Es fundamental seleccionar las pruebas
• Sólo las pruebas que revelen errores son las que
merecen la pena
• El objetivo
objeti o es ENCONTRAR ERRORES
– Una prueba que no detecta un error es un
fracaso
– Una prueba que detecta errores es exitosa
4

•2
•03/06/2010

Proceso
Configuración
del software Evaluación

Prueba
Depuración

Configuración Resultado
de la prueba Esperado

Pasar de nuevo
todas las pruebas

Características de una Prueba


• Ha de tener una alta probabilidad de encontrar
un fallo.
fallo
• Debe centrarse en dos objetivos:
– Buscar si el software no hace lo que debe hacer
– Buscar si el software hace lo que no debe hacer
• No debe ser redundante.
• Una buena prueba no debería ser ni demasiado
sencilla
ill nii d
demasiado
i d compleja.
l j
• Las pruebas deben pasarse de manera
independiente unas de otras, para evitar
enmascarar errores.
6

•3
•03/06/2010

Tipos de prueba
• Las pruebas se realizan a lo largo de todo el
desarrollo del sistema:
– Prueba modular o unitaria
– Prueba de integración
• Top-down
• Bottom-up
– Prueba del sistema
– Prueba de aceptación
– Prueba de regresión
• Otros tipos de pruebas
– Pruebas de estrés
– Pruebas de carga
7

Tipos de prueba
Pruebas unitarias o modulares
• Prueban el correcto funcionamiento de un
módulo de código
• Características:
– Automatizable
– Repetibles o Reutilizables
– Completas
– I d
Independientes
di t
• Deben estar correctamente documentadas
– Debe describir qué verifica y valida la prueba

•4
•03/06/2010

Diseño de Pruebas
• El diseño de las pruebas se dividen en dos:
– Técnicas de caja negra:
• Se centran en la funcionalidad del sistema.
– Técnicas de caja blanca:
• Se fundamentan en cómo está hecho el sistema.
Se utiliza el conocimiento sobre cómo está
codificado para definir las pruebas.

Pruebas de Caja Negra(I)


• La selección de los casos de prueba se basa en
cómo funciona el sistema
• Las pruebas de caja negra exhaustiva son
inviables, se requiere una prueba por cada
combinación de los valores de entrada
• El caso bien elegido es el que reduce la
necesidad de otros casos,
casos cubriendo un
conjunto extenso de estos

11

•5
•03/06/2010

Pruebas de Caja Negra(III)


/**
* Calcula el factorial de un número
* <br><B>PRE:</B> n > = 0
* <br><B>POST:</B> res = n!
* @param n
* @return n!
*/
public static long factorial1 (int n) {
if (n < 0) throw new IllegalArgumentException();
if (n <= 1 )
return 1;
else
return n * factorial1 (n-1);
}

12

Pruebas de Caja Negra(II)


• Para probar el factorial:
– IInviable
i bl hhacerlo
l con ttodos
d llos números
ú naturales.
t l
– Debería probar con un i < 0, i =0, i > 0
• Si i = 0 → 1
Entradas correctas
• Si i > 0 i! Entradas
• Si i < 0 → IllegalArgumentException incorrectas

¿Es necesario?

13

•6
•03/06/2010

Pruebas de Caja Negra(VII)


• Los métodos para seleccionar los casos de
prueba son:
– Método de clases de equivalencia
– Análisis de valores frontera o valores límite
– Adivinación de errores

17

Pruebas de Caja Negra(VIII)


(Clases de Equivalencia(I))

• Consiste en dividir las posibles entradas en


q
clases de equivalencia, , de tal forma q
que todos
los miembros de una clase prueben las mismas
propiedades del sistema.
• Sólo es necesario seleccionar un elemento de
cada clase para realizar las pruebas.
• Las etapas son:
– Identificación de clases de equivalencia
q
– Crear los casos de prueba

18

•7
•03/06/2010

Pruebas de Caja Negra(VIII)


(Clases de Equivalencia(II))

• Para la identificación de clases haremos:


– Las precondiciones para las entradas nos darán
dos o más grupos (ejemplo: números positivos
entre 2 y 99)
– También hay que considerar las restricciones en
las salidas
– Habrá dos tipos de clases:
• Válidas: Los valores cumplen las restricciones o
precondiciones de entrada
• No válidas: Entradas erróneas, no cumplen las
restricciones o precondiciones de entrada

19

Pruebas de Caja Negra(IX)


(Análisis de Valores Límite(I))

• “Los errores se esconden en los rincones y se


límites .
aglomeran en los límites”
• Consiste en seleccionar como casos de prueba
aquellos que caen en la frontera de las clases
de equivalencia (situados en los márgenes de la
clase).
• Los casos de prueba que exploran las
condiciones límite, producen mejores resultados
a la hora de detectar defectos.

25

•8
•03/06/2010

Pruebas de Caja Negra(IX)


(Análisis de Valores Límite(II))

• Diferencias con clases de equivalencia:


– Se seleccionan los márgenes de la clase como
casos de prueba.
– Han de comprobarse también los valores límite
de las salidas.
• La selección de los valores límite es heurística
es decir se basa en la experiencia
• Para determinarlos nos basamos en las
restricciones de las entradas y de las salidas.

26

Pruebas de Caja Negra(X)


(Adivinación de Errores)

• Consiste en “tratar” de imaginar cuáles son los


errores que se pueden haber cometido con
mayor probabilidad.
• No existen directivas, la técnica se basa en la
intuición de casos especiales.
• La experiencia ayuda a “predecir” los fallos más
probables de un sistema

28

•9
•03/06/2010

Pruebas de Caja Blanca (I)


• La elección de los casos de prueba se basa en
el conocimiento qque se tenga
g acerca de la
estructura del módulo (diseño detallado, código
fuente, ...)
• La prueba ideal o exhaustiva consiste en
recorrer todas las secuencias de sentencias o
caminos dentro del programa
• En la mayoría de los casos las pruebas
exhaustivas
h ti son iimpracticables,
ti bl porque ell
número de caminos puede ser muy grande

29

Pruebas de Caja Blanca (II)


• Ejemplo: Un programa de 50 líneas con 25 “if”
en secuencia 225=33
=33’5
5 millones de sucesiones
o caminos distintos
• Sin embargo, pueden probarse ciertos caminos
o secuencias, elegidos según un criterio de
cobertura.

30

•10
•03/06/2010

Pruebas de Caja Blanca (III)


• Criterios:
– Cobertura de sentencia
- -
– Cobertura de decisión de ramificación
coste y caminos a tratar

– Cobertura de condición

Confianza
– Cobertura de bucle

+ +

31

Pruebas de Caja Blanca (IV)


(Cobertura de Sentencias (I))

• Se utilizan los casos de prueba suficientes para


que cada sentencia se ejecute al menos una
vez (if ... else ... es una sentencia)
• Es un criterio pobre y de escasa utilidad
• Un defecto en el cuerpo de un “IF” podría no ser
detectado (en alguna de las ramas)
• Puede detectar fragmentos
g de código
g
inaccesible (inútil)

32

•11
•03/06/2010

Pruebas de Caja Blanca (IV)


(Cobertura de Sentencias (II))
Bastaría con que se ejecutara
private boolean esValida() { una rama del switch
switch (this.mes) {// SW
case ENERO: case MARZO: case MAYO: case JULIO:
case AGOSTO: case OCTUBRE: case DICIEMBRE: // Meses de 31 días
if (this.dia >= 1 && this.dia <= 31) return true;
else return false;
case FEBRERO:
if (esBisiesto()&& this.dia >= 1 && this.dia <= 29)
return true;
else
if (this.dia >= 1 && this.dia <= 28) return true;
else return false;
case ABRIL:
case JUNIO:
case SEPTIEMBRE:
return this.dia >= 1 && this.dia <= 30;
}// SW
return false;
}

33

Pruebas de Caja Blanca (V)


(Cobertura de Decisión de Ramificación(I))

• Se han de determinar casos suficientes como


para que cada decisión sea evaluada al menos
una vez como verdadera y otra como falsa
• Es un criterio débil. Un error en un elemento de
la condición puede no ser detectado, ya que
para que una condición sea cierta o falsa no es
preciso evaluar todos los elementos de ésta.

34

•12
•03/06/2010

Pruebas de Caja Blanca (V)


(Cobertura de Decisión de Ramificación(II))
Habría que probar con: Enero,
private boolean esValida() { Febrero y Abril
switch (this.mes) {// SW
case ENERO: case MARZO: case MAYO: case JULIO:
case AGOSTO: case OCTUBRE: case DICIEMBRE: // Meses de 31 días
if (this.dia >= 1 && this.dia <= 31) return true;
else return false; Con “día >=1 y dia <= 31” y
case FEBRERO:
Con día > 31
if (esBisiesto()&& this.dia >= 1 && this.dia <= 29)
return true;
else
if (this.dia >= 1 && this.dia <= 28) return true;
else
e se return
etu false;
a se;
case ABRIL: case JUNIO: case SEPTIEMBRE:
return this.dia >= 1 && this.dia <= 30;
}// SW
return false; Así con todas los if/else hasta
asegurar que se ejecutan
}
todas las ramas
35

Pruebas de Caja Blanca (VI)


(Cobertura de Condición (I))

• Consiste en escribir tantos casos de prueba


como para que todas las condiciones se
prueben con todos los casos posibles de
Verdadero y Falso al menos una vez.

36

•13
•03/06/2010

Pruebas de Caja Blanca (VI)


(Cobertura de Condición (II))
Habría que probar con: Enero,
private boolean esValida() { Febrero, Marzo, Abril, …
switch (this.mes) {// SW
case ENERO: case MARZO: case MAYO: case JULIO:
case AGOSTO: case OCTUBRE: case DICIEMBRE: // Meses de 31 días
if (this.dia >= 1 && this.dia <= 31) return true;
else return false; Con “día >=1 y dia <= 31” y
case FEBRERO:
Con día > 31 y
if (esBisiesto()&& this.dia >= 1 && this.dia <= 29)
return true; Con día < 1
else
if (this.dia >= 1 && this.dia <= 28) return true;
else
e se return
etu false;
a se;
case ABRIL: case JUNIO: case SEPTIEMBRE:
return this.dia >= 1 && this.dia <= 30;
}// SW Así con todas los if/else hasta asegurar que se
return false; ejecutan todas las ramas con todas las posibilidades
} que hay para evaluar la condición de true o false

37

Pruebas de Caja Blanca (VI)


(Cobertura de Condición (II))
Habría que probar con: Enero,
private boolean esValida() { Febrero, Marzo, Abril, … Diciembre
switch (this.mes) {// SW
case ENERO: case MARZO: case MAYO: case JULIO:
case AGOSTO: case OCTUBRE: case DICIEMBRE: // Meses de 31 días
if (this.dia >= 1 && this.dia <= 31) return true;
else return false; Con “día >=1 y dia <= 31” y
case FEBRERO:
Con día > 31 y
if (esBisiesto()&& this.dia >= 1 && this.dia <= 29)
return true; Con día < 1
else
if (this.dia >= 1 && this.dia <= 28) return true;
else
e se return
etu false;
a se;
case ABRIL: case JUNIO: case SEPTIEMBRE:
return this.dia >= 1 && this.dia <= 30;
}// SW Así con todas los if/else hasta asegurar que se
return false; ejecutan todas las ramas con todas las posibilidades
} que hay para evaluar la condición de true o false

38

•14
•03/06/2010

Pruebas de Caja Blanca (VII)


(Cobertura de Bucle(I))

• Los bucles son segmentos controlados por


condiciones qque se ppueden repetir
p hasta n
veces (iteraciones)
• Un error en la codificación de la condición
implicará que el número de veces que se
ejecute no sea el correcto
• Hay que definir casos de prueba que estudien:
– Pasar por alto totalmente el bucle
– Pasar una sola vez por el bucle
– Hacer m pasos por el bucle con m < n
– Hacer n-1, n y n + 1 pasos por la condición del bucle
– Cobertura de condiciones
39

Pruebas de Caja Blanca (VII)


(Cobertura de Bucle(II))
public ListaOrdenada<Informacion> borrar (Informacion
elemento) {
if ((this.estaVacia())
()) return this;;
//Si no está vacía hay que empezar el proceso
Nodo<Informacion> resto=this.cabeza;
Nodo<Informacion> restoAnt=null;
while (resto!=null && //No se ha llegado al final
resto.darDato().compareTo(elemento)<0)
{//W -El primer elemento
restoAnt=resto; -Elemento central
resto=resto.darSiguiente();
}//W -El último elemento
-El elemento no está
if (resto==this.cabeza
( thi b && //Es
// el
l primer
i elemento
l t
resto.darDato().compareTo(elemento)==0) //Caso trivial
cabeza=restoAnt;
else
if (resto!=null && resto.darDato().compareTo(elemento)==0)
restoAnt.fijarSiguiente(resto.darSiguiente());
return this; }
40

•15
•03/06/2010

Revisiones de Código
• Comprobación de escritorio (desk checking).
• Comprobación por pares o iguales (peer review).
• Inspección:
I ió
– Un grupo de desarrolladores se asegura de que el código fuente
cumple una serie de condiciones (checklist): Inicialización de
variables, control de límites de arrays, liberación de memoria
dinámica, etc.
• Walkthrough o visita guiada:
– La realiza un grupo en el que al menos está el programador del
código fuente a revisar
– Una persona ajena al código fuente prepara un conjunto de
casos de prueba.
– Se ejecuta “mentalmente” en grupo el código para los casos de
prueba. Ejecución guiada por el programador del código.
– Se plantean preguntas al programador del código.

41

Pruebas de Integración (I)


• Se realizan durante la construcción del sistema.
• Se van introduciendo módulos hasta haber
probado el sistema como conjunto.
• Se suponen que los módulos que se incorporan
son correctos por separado por haber
superado las pruebas unitarias.
• Comprueba
p q
que las interfaces entre los diversos
módulos son correctas.

42

•16
•03/06/2010

Pruebas de Integración (II)


• Para realizar este tipo de pruebas hay que
comprobar:
– Corrección de la sintaxis en la invocación de
procedimientos y funciones.
– Compatibilidad de tipos entre los argumentos del
procedimiento o función y los parámetros de
llamada.
– Corrección y completitud
p de las especificaciones
p
de los módulos (los módulos hacen lo que tienen
que hacer).

43

Pruebas de Integración (III)


• Técnica top-down: Consiste en empezar la
integración por los módulos que están en los
niveles superiores de abstracción, e integrar
incrementalmente los inferiores. Suele requerir
el diseño de emuladores de los niveles
inferiores.
• Técnica bottom-up: Se empieza la integración
y la prueba por los módulos inferiores
inferiores.

44

•17
•03/06/2010

Pruebas del Sistema


• Se realizan cuando todos los módulos se han
integrado y su objetivo es comprobar que el
sistema satisface los requisitos del usuario,
tanto funcionales como no funcionales

50

Pruebas de Aceptación
• Se realizan una vez que el sistema se ha
implantado en su entorno real de
funcionamiento.
• El objetivo es demostrar al cliente que el
sistema satisface sus necesidades.
• Tipos:
– Pruebas alfa (en el entorno de desarrollo)
– Pruebas beta (en el entorno del cliente)

51

•18
•03/06/2010

Pruebas de Regresión
• El objetivo es comprobar que toda nueva
versión de un producto software no es de menor
calidad que la anterior.
• Implica pasar nuevamente todas las pruebas.
• Es conveniente automatizar el proceso de
pruebas todo lo que se pueda.

52

Plan de Pruebas (I)


• Es necesario documentar todo el proceso.
• Para
P cada
d prueba
b hhay que especificar:
ifi
– Qué propiedades se desean probar (corrección,
robustez, fiabilidad, amigabilidad, ...)
– Especificar cómo se mide el resultado
– Especificar en qué consiste la prueba, indicando
hasta el último detalle de cómo se ejecuta
– Definir cuál es el resultado que se espera

53

•19
•03/06/2010

Plan de Pruebas (II)


• Fases en la ejecución de una prueba
–P á b l Fase
Pre-ámbulo: F preliminar
li i que especifica
ifi llos
pasos a seguir para llevar al sistema al estado
que se desea para realizar la prueba.
– Cuerpo: es la prueba en sí.
– Post-ámbulo: Es el conjunto de acciones que
llevan al sistema a un estado “reconocible”
reconocible para
seguir probándolo. Por ejemplo, reiniciarlo.

54

Plan de Pruebas (III)


• Un método para realizar las pruebas podría ser:
1 Pruebas de caja negra analizando valores
1.
límite, tanto de entrada como de salida
2. Identificar las clases de equivalencia y añadir
más pruebas de caja negra para comprobar
valores normales
3. Pruebas basadas en “adivinación de errores”
4. Añadir casos de caja j blanca hasta alcanzar la
cobertura deseada, sobre todo, en las partes
más críticas de la aplicación.

55

•20
•03/06/2010

JUNIT 4.5

56

JUnit
• Es un framework que permite definir y
automatizar pruebas.
pruebas
• Facilita el proceso de repetir las pruebas.
• Está desarrollada para java.
• Hay versiones para otros lenguajes.
• Se puede encontrar en http://www.junit.org
• La versión 4.5 requiere de java 1.5 o superior
• Para poder usarlo se requiere que en el
classpath esté junit-4.5.jar.
57

•21
•03/06/2010

JUnit
• JUnit trabaja con anotaciones ‘@’
• @Test: Indica que el método que viene a
continuación es una prueba:
/**
* Test method for {@link Ejemplo2#factorial2(int)}.
*/
@Test
public void testFactorial2Case1() {
int entrada = 0;
int resultadoEsperado = 1;
assertEquals(resultadoEsperado,
Ejemplo2.factorial2 (entrada));
}

58

JUnit
• Un test se marca como:
– Error: se ha producido una excepción no esperada o vence
un timeout
– Fail: No cumple el assert o no se genera una excepción
esperada
• Para implementar una prueba se puede utilizar
org.junit.Assert:
– static void assertTrue(boolean condition)
– static void assertTrue( String msg, boolean condition)
– static
t ti void l (St i msg, Object
id assertEquals(String
tE Obj t expected,
t d
Object actual)
– static void assertArrayEquals(Object[] expecteds,
Object[] actuals)
– etc.
59

•22
•03/06/2010

JUnit
• ¿Cómo probamos que un método genera una
excepción p.e.
p e factorial ((-1)?
1)?
• @Test (expected = exception.class)
/**
* Test method for {@link Ejemplo2#factorial2(int)}.
*/
@Test (expected = IllegalArgumentException.class)
public void testFactorial2Case3() {
int entrada = -1;
Ejemplo2.factorial2 (entrada);
}

60

JUnit
• ¿Cómo detectamos que no tarda mucho?
• @Test
@T t (ti
(timeoutt = milisegundos)
ili d )
/**
* Test method for {@link Ejemplo2#factorial2(int)}.
*/
@Test(timeout = 1)
public void testFactorial2Case2() {
int entrada = 20;
long resultadoEsperado =
Long.valueOf("2432902008176640000");
assertEquals(resultadoEsperado, Ejemplo2.factorial2
(entrada));
}
61

•23
•03/06/2010

JUnit
• Como se ha comentado en este tema, hay que
configurar el sistema para realizar las pruebas
• JUnit proporciona dos anotaciones para esto:
– @BeforeClass: Sólo se realiza una vez antes de que se
ejecute la primera prueba
– @Before: Se ejecuta justo antes de cada prueba
• Tenemos los pasos equivalentes para la finalización:
– @AfterClass se ejecuta al terminar todas las pruebas
– @After
@Aft se ejecuta
j t después
d é d de cada
d prueba
b
• Véase:
– trunk\ejemplos\Pruebas\src\PruebaAnotaciones.java
– trunk\ejemplos\Pruebas\src\PruebaColas.java

62

•24

Anda mungkin juga menyukai