lprg documentacion y pruebas unitarias

16
1 Laboratorio de Programación Documentación Pruebas Unitarias Dpto. de Ingeniería de Sistemas Telemáticos http://www.lab.dit.upm.es/~lprg/ febrero 2010 Documentación y Pruebas 2 Documentación

Upload: arianna-perez-r

Post on 26-Jun-2015

313 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: LPRG Documentacion y Pruebas Unitarias

1

Laboratorio de Programación

DocumentaciónPruebas Unitarias

Dpto. de Ingeniería de Sistemas Telemáticoshttp://www.lab.dit.upm.es/~lprg/

febrero 2010

Documentación y Pruebas 2

Documentación

Page 2: LPRG Documentacion y Pruebas Unitarias

2

Documentación y Pruebas 3

¿Qué es documentar?

� Documentar el código de un programa es añadir suficiente información como para explicar lo que hace, punto por punto, de forma que no sólo los ordenadores sepan qué hacer, sino que además los humanos entiendan qué están haciendo y por qué.

� No se trata sólo de rematar el trabajo, sino que responde a necesidades reales que pueden aparecer en el futuro:� Extender el programa con nuevas funcionalidades� Adaptarlo a un nuevo escenario

Documentación y Pruebas 4

¿Qué hay que documentar?

� Reglas básicas:� Documentar/explicar aquello que no es evidente� No repetir lo que se hace, sino explicar por qué se hace así

� Y esto se traduce en:� ¿de qué se encarga una clase? ¿un paquete? � ¿qué hace un método? � ¿cuál es el uso esperado de un método? � ¿para qué se usa una variable? � ¿cuál es el uso esperado de una variable? � ¿qué algoritmo estamos usando? ¿de dónde lo hemos sacado? � ¿qué limitaciones tiene el algoritmo? ¿... la implementación? � ¿qué se debería mejorar ... si hubiera tiempo?

Page 3: LPRG Documentacion y Pruebas Unitarias

3

Documentación y Pruebas 5

Tipos de comentarios

� javadoc� Delimitados por “/**” y “*/”� Pueden abarcar varias líneas (que quizás comiencen por “*”)� Permiten generar documentación externa al programa

� una línea� Comienzan con “//” y terminan con la línea� Para documentar código que no se desea que aparezca en

documentación externa� Pueden utilizarse varios seguidos

� tipo C� Comienzan con “/*” y terminan con “*/”� Pueden abarcar varias líneas� Permiten “eliminar” código que no queremos olvidar del todo

Documentación y Pruebas 6

¿Cuándo documentar?

� Por obligación (javadoc)� al principio de cada clase� al principio de cada método� antes de cada variable de clase

� Por conveniencia (una línea)� al principio de un fragmento de código no evidente� a lo largo de los bucles

� Por si acaso (una línea)� siempre que se haga algo raro� siempre que el código no sea evidente

Page 4: LPRG Documentacion y Pruebas Unitarias

4

Documentación y Pruebas 7

Javadoc

� Es una herramienta del kit de desarrollo que permite generar documentación Web a partir del código

� Más que ayudar a comprender el código, se centra en la interfaz (API – Application Programming Interfaz) de las clases y paquetes Java

� Javadoc exige unos comentarios especiales:/*** Parte descriptiva* Que puede abarcar varias frases o párrafos* * @etiqueta texto específico para la etiqueta*/

Documentación y Pruebas 8

Javadoc – Clases e Interfaces

� Al menos, deben usarse las etiquetas� @author� @version

� Etiquetas posibles

@author Nombre del autor@version Identificació de versión y fecha

@see Referencia a otras clases y métodos

@since Indica desde qué versión o fecha existe la clase o interfaz en el paquete

@deprecated Esta clase no debería usarse pues puede desaparecer en próximas versiones

Page 5: LPRG Documentacion y Pruebas Unitarias

5

Documentación y Pruebas 9

Javadoc – Constructores y Métodos

� Al menos, deben usarse las etiquetas� @param – una por argumento de entrada� @return – si el método no es void� @exception – una por tipo de Exception que pueda lanzar

� Etiquetas posibles

@param Nombre del parámetro Descripción de su significado y uso@return Descripción de lo que se devuelve

@exception Nombre de la excepción Excepciones que pueden lanzarse

@since Indica desde qué versión o fecha existe este constructor o método en la clase

@deprecated Este método no debería usarse pues puede desaparecer en próximas versiones

Documentación y Pruebas 10

Javadoc – Atributos

� No hay ninguna etiqueta obligatoria� Etiquetas posibles

@since Indica desde qué versión o fecha existe este atributo en la clase

@deprecated Este atributo no debería usarse pues puede desaparecer en próximas versiones

Page 6: LPRG Documentacion y Pruebas Unitarias

6

Documentación y Pruebas 11

Ejecución de Javadoc

� <Directorio_Instalación>\javadoc Programa.java� Múltiples opciones (entre ellas):

usage: javadoc [options] [packagenames] [sourcefiles] [classnames] [@files]

-public Show only public classes and members

-protected Show protected/public classes and members (default)

-package Show package/protected/public classes and members

-private Show all classes and members

-sourcepath <pathlist> Specify where to find source files

-classpath <pathlist> Specify where to find user class files

-verbose Output messages about what Javadoc is doing

-d <directory> Destination directory for output files

-version Include @version paragraphs

-author Include @author paragraphs

-docfilessubdirs Recursively copy doc-file subdirectories

-splitindex Split index into one file per letter

-windowtitle <text> Browser window title for the documenation

-doctitle <html-code> Include title for the overview page

-header <html-code> Include header text for each page

-footer <html-code> Include footer text for each page

-bottom <html-code> Include bottom text for each page

Documentación y Pruebas 12

Referencias

� How to Write Doc Comments for the Javadoc Tool� http://java.sun.com/j2se/javadoc/writingdoccomments/

� Ejemplo de Javadoc� http://java.sun.com/javase/6/docs/api/

Page 7: LPRG Documentacion y Pruebas Unitarias

7

Documentación y Pruebas 13

Pruebas Unitarias

Documentación y Pruebas 14

Objetivo

� El objetivo único de las pruebas es encontrar errores en el código� antes de que aparezcan en ejecución

� Una batería de pruebas es tanto mejor cuanto menos errores pasan desapercibidos

� Un programa es aceptable cuando:� Hace lo que se acordó que debería hacer en las especificaciones

� No hace lo que no debe hacer� Jamás debería entregarase un programa sin haberlo probado

Page 8: LPRG Documentacion y Pruebas Unitarias

8

Documentación y Pruebas 15

Enfoque psicológico

�El que desarrolla� comprueba que el programa funciona� con todo lo que se le ocurre que debe funcionar

�El que prueba� comprueba que el programa no falla� con todo lo que se le ocurre que puede fallar

Documentación y Pruebas 16

Tipos de prueba

� Pruebas de caja blanca: analizar el propio código (pruebas estructurales)

� Pruebas de caja negra: sin ver el código, probar la funcionalidad según especificaciones (pruebas funcionales)

� Pruebas de integración: probar cómo funciona el sistema completo, compuesto por módulos distintos.

� Pruebas de aceptación: realizadas el cliente para ver si se le entrega lo que pidió.

� Pruebas de regresión: tras añadir algo nuevo, para ver que no se ha descabalado la funcionalidad que ya había.

� Pruebas de robustez o solidez, de aguante, de prestaciones, etc.

Page 9: LPRG Documentacion y Pruebas Unitarias

9

Documentación y Pruebas 17

Caja Negra: Casos de Prueba

� ¿Qué hay que probar?� Todo lo que dice la especificación

� Manual� Instrucciones� Documentación adicional

� Hasta completar el 100% de cobertura

Documentación y Pruebas 18

Caja Negra: Datos de Prueba

� Divida el espacio de pruebas en clases de equivalencia� conjuntos de datos con comportamientos similares

� Elija un dato “normal” de una clase de equivalencia� Pruebe con todos los datos “frontera” (valores extremos)

� Añada aquellos casos donde piense que el programador puede haberse equivocado

� Pruebe todas las combinaciones de � {datos x comportamiento}

Page 10: LPRG Documentacion y Pruebas Unitarias

10

Documentación y Pruebas 19

Caja Negra: Ejemplo

� Probar un método de ordenación de un array� Input: 2 10 6 3 8 7 9 5 4 1� Output: 1 2 3 4 5 6 7 8 9 10

� ¿Qué hay que probar?� que todos los datos están en orden ascendente� for (int i= 1; i < n; i++)

assert (dato[i-1] <= dato[i]);

� ¿Con qué datos probar?� Casos normales: N datos

� 10 datos al azar� Casos singulares: 0 y 1 datos� “sospechas”

� Elementos ya ordenados: 1 2 3 4 5 6 7 8 9 10� Elementos ordenados al revés: 10 9 8 7 6 5 4 3 2 1

Documentación y Pruebas 20

Caja Blanca: Casos de Prueba

� ¿Qué hay que probar?� Ejecutar, al menos, una vez cada sentencia

� cobertura de sentencias� Ejecutar al menos una vez cada condición con resultado cierto y

falso� cobertura de ramas

� Hasta completar el 100% del código� if (...)

� Si T, si F� switch (...)

� Cada ‘case’ + default� Cobertura de bucles

� for -> 3 pruebas: 0 veces, 1 vez, n>1 veces� repeat -> 2 pruebas: 1 vez, n>1 veces� while-> 3 pruebas: 0 veces, 1 vez, n>1 veces

Page 11: LPRG Documentacion y Pruebas Unitarias

11

Documentación y Pruebas 21

JUnit: Pruebas sistemáticas

� Prueba unitaria: una prueba individual de un método o clase.� Prueba unitaria ad-hoc: por ejemplo, cuando creamos un objeto de

cierta clase con BlueJ e invocamos manualmente un método del mismo con distintas entradas para ver si funciona.

� Sin embargo, con este tipo de pruebas no se puede trabajar eficiente y sistemáticamente.

� Cada vez que cambiamos algo en el método o clase tendríamos que volver a pasar todas las pruebas para asegurarnos de que “nada se ha descabalado”. Es decir, realizar pruebas de regresión.

� Para ello, vendría muy bien algo que nos permitiera definir sistemáticamente una serie de pruebas y ejecutarlasautomáticamente, tantas veces como necesitáramos.

� JUNIT nos permite hacer esto (www.junit.org)

Documentación y Pruebas 22

JUnit: Procedimiento

� Antes de implementar una determinada funcionalidad, piensa cómo deberías probarla para verificar que se comporta correctamente. Esto permite desarrollar la funcionalidad teniendo las ideas muy claras de lo que debería hacer.

� Escribe el código que implementa la funcionalidad deseada.� Escribe el código de las pruebas inmediatamente después.� Ejecuta las pruebas que hiciste.� Corrige la unidad de código que implementa la funcionalidad deseada hasta que

pase todas y cada una de las pruebas.� Al añadir una nueva funcionalidad, repite el ciclo: piensa en cómo probarla,

codifica la funcionalidad, codifica las pruebas, ejecuta todas las pruebas que hiciste (nuevas y viejas). No sigas hasta que el código pase absolutamente todaslas pruebas.

� Así una y otra vez para cada nueva funcionalidad que implementes. Lo vemos con un ejemplo.

Page 12: LPRG Documentacion y Pruebas Unitarias

12

Documentación y Pruebas 23

JUnit: Ejemplo (1)

Desarrollar un método estático que tome un array de enteros como argumento y devuelva el mayor valor encontrado en el array.

public class MayorNumero {/**

* Devuelve el elemento de mayor valor de una lista* @param list Un array de enteros* @return El entero de mayor valor de la lista

*/public static int mayorNumero(int lista[]) {

return 0; // para que compile, hasta que //desarrollemos el método

}}

Documentación y Pruebas 24

JUnit: Ejemplo (2)

¿Qué pruebas pueden hacerse?

� Caso normal: array con valores cualesquiera� [3, 7, 9, 8] -> 9

� El mayor número se encuentra al principio o al final de la lista� [9, 7, 8] -> 9� [8, 7, 9] -> 9

� El mayor número está duplicado en el array� [9, 7, 9, 8] -> 9

� Sólo hay un elemento en el array� [7] -> 7

� Array compuesto por números negativos� [-4, -6, -7, -22] -> -4

Page 13: LPRG Documentacion y Pruebas Unitarias

13

Documentación y Pruebas 25

JUnit: Ejemplo (3)

Escribimos el código del método:

/*** Devuelve el elemento de mayor valor de una lista* * @param list Un array de enteros* @return El entero de mayor valor de la lista*/public static int mayorNumero(int lista[]) {

int indice, max = Integer.MAX_VALUE;for (indice = 0; indice < lista.length-1; indice++) {

if (lista[indice] > max) {max = lista[indice];

}}return max;

}

Documentación y Pruebas 26

JUnit: Ejemplo (4)Escribimos el código de las pruebas:import junit.framework.*;

public class TestMayorNumero extends TestCase {public TestMayorNumero() {}

public void testSimple() { assertEquals(9, MayorNumero.mayorNumero(new int[] {3, 7, 9, 8}));

}

public void testOrden() {assertEquals(9, MayorNumero.mayorNumero(new int[] {9, 7, 8}));assertEquals(9, MayorNumero.mayorNumero(new int[] {7, 9, 8}));assertEquals(9, MayorNumero.mayorNumero(new int[] {7, 8, 9}));

}

public void testDuplicados() {assertEquals(9, MayorNumero.mayorNumero(new int[] {9, 7, 9, 8}));

}

public void testSoloUno() {assertEquals(7, MayorNumero.mayorNumero(new int[] {7}));

}

public void testTodosNegativos() {assertEquals(-4, MayorNumero.mayorNumero(new int[] {-4, -6, -7, 22}));

}

public static void main (String args[]) {junit.textui.TestRunner.run(TestMayorNumero.class);

}}

Page 14: LPRG Documentacion y Pruebas Unitarias

14

Documentación y Pruebas 27

JUnit: Ejemplo (4)Fallos detectados:

� Error de concepto: MAX_VALUE por MIN_VALUE� Valor frontera en un bucle� Error en la propia definición de las pruebas

Documentación y Pruebas 28

JUnit

� Marco para desarrollar pruebas unitarias� Pasos:

� Importar las clases de JUNIT necesarias� Definir la clase de pruebas:

� Debe extender la clase “TestCase”� Definir los métodos de prueba

� Deben comenzar por “test”� Serán ejecutados automáticamente por JUNIT

� Definir un main o ejecutar desde un IDE� junit.textui.TestRunner.run(<clase>)

Page 15: LPRG Documentacion y Pruebas Unitarias

15

Documentación y Pruebas 29

Junit: comprobaciones� assertEquals (valor_esperado, valor_real);

� Los valores pueden ser de cualquier tipo� Si son arrays, no se comprueban elemento a elemento, sólo la referencia

� assertTrue (condición_booleana)� assertFalse (condición_booleana)� assertSame (Objeto esperado, Objeto real)

� Comprueba que son la misma referencia� assertNotSame (Objeto esperato, Objeto obtenido)

� Comprueba que son referencias distintas� assertNull (Objeto)

� Comprueba que el objeto es Null� assertNotNull (Objeto objeto)

� Comprueba que el objeto no es Null� fail (string Mensaje)

� Imprime el mensaje y falla� Útil para comprobar que se capturan excepciones

Documentación y Pruebas 30

Junit: Uso de las comprobaciones� En una función de prueba (“testXXX”), se pueden poner tantos métodos

de comprobación como sean necesarios para implementar el caso de prueba concreto.

� A la hora de ejecutar la función prueba (“testXXX”), en cuanto falle uno de los métodos de comprobación se para la ejecución. No se ejecutan el resto de métodos de comprobación tras el que falló.

� En ese caso, antes de seguir es MUY aconsejable corregir el fallo que se ha producido.

� En general hay que comprobar que un método lanza todas las excepciones que se han declarado en el mismo cuando debe. Y que no las lanza cuando no hay motivo para ello. Esta es la utilidad del método fail.public void testExcepcionOrdenarListaNula( ) {

try {

ordena_lista(null);

fail(“Debería haber lanzado una excepción”);

} catch (RuntimeException e) { }

}

Page 16: LPRG Documentacion y Pruebas Unitarias

16

Documentación y Pruebas 31

Junit: setUp & tearDown� Se pueden poner métodos para envolver las pruebas:

public void setUp() { ...; }

public void tearDown() { ...; }

setUp()

test001()

tearDown()

setUp()

test002()

tearDown()

setUp()

test003()

tearDown()