You are on page 1of 16

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

Documentación y Pruebas 2

1

punto por punto. si hubiera tiempo? Documentación y Pruebas 4 2 . ¿Qué es documentar?  Documentar el código de un programa es añadir suficiente información como para explicar lo que 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? ¿... sino que además los humanos entiendan qué están haciendo y por qué. de forma que no sólo los ordenadores sepan qué hacer.. la implementación?  ¿qué se debería mejorar .. 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 3 ¿Qué hay que documentar?  Reglas básicas:  Documentar/explicar aquello que no es evidente  No repetir lo que se hace.  No se trata sólo de rematar el trabajo.

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 5 ¿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 Documentación y Pruebas 6 3 .

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. 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 Documentación y Pruebas 8 4 . 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 7 Javadoc – Clases e Interfaces  Al menos.

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 9 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 Documentación y Pruebas 10 5 .

sun. Ejecución de Javadoc  <Directorio_Instalación>\javadoc Programa.sun.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 11 Referencias  How to Write Doc Comments for the Javadoc Tool  http://java.com/j2se/javadoc/writingdoccomments/  Ejemplo de Javadoc  http://java.com/javase/6/docs/api/ Documentación y Pruebas 12 6 .

Pruebas Unitarias Documentación y Pruebas 13 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 Documentación y Pruebas 14 7 .

etc. para ver que no se ha descabalado la funcionalidad que ya había.  Pruebas de robustez o solidez. Documentación y Pruebas 16 8 . de aguante. 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 15 Tipos de prueba  Pruebas de caja blanca: analizar el propio código (pruebas estructurales)  Pruebas de caja negra: sin ver el código. de prestaciones. probar la funcionalidad según especificaciones (pruebas funcionales)  Pruebas de integración: probar cómo funciona el sistema completo.  Pruebas de regresión: tras añadir algo nuevo.  Pruebas de aceptación: realizadas el cliente para ver si se le entrega lo que pidió. compuesto por módulos distintos.

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 17 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} Documentación y Pruebas 18 9 .

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 (. n>1 veces  repeat -> 2 pruebas: 1 vez. 1 vez.)  Cada ‘case’ + default  Cobertura de bucles  for -> 3 pruebas: 0 veces.. n>1 veces  while-> 3 pruebas: 0 veces. n>1 veces Documentación y Pruebas 20 10 . i < n.. si F  switch (. 1 vez.)  Si T. i++) assert (dato[i-1] <= dato[i]).. 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.  ¿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 19 Caja Blanca: Casos de Prueba  ¿Qué hay que probar?  Ejecutar.. al menos.

 Sin embargo. No sigas hasta que el código pase absolutamente todas las pruebas.  Escribe el código que implementa la funcionalidad deseada.  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”.  Escribe el código de las pruebas inmediatamente después.  Prueba unitaria ad-hoc: por ejemplo.  Al añadir una nueva funcionalidad. piensa cómo deberías probarla para verificar que se comporta correctamente. Es decir.  Para ello. codifica la funcionalidad.  Así una y otra vez para cada nueva funcionalidad que implementes. cuando creamos un objeto de cierta clase con BlueJ e invocamos manualmente un método del mismo con distintas entradas para ver si funciona.  Corrige la unidad de código que implementa la funcionalidad deseada hasta que pase todas y cada una de las pruebas. Esto permite desarrollar la funcionalidad teniendo las ideas muy claras de lo que debería hacer. realizar pruebas de regresión.  JUNIT nos permite hacer esto (www. con este tipo de pruebas no se puede trabajar eficiente y sistemáticamente. Documentación y Pruebas 22 11 . tantas veces como necesitáramos. JUnit: Pruebas sistemáticas  Prueba unitaria: una prueba individual de un método o clase.  Ejecuta las pruebas que hiciste. codifica las pruebas.org) Documentación y Pruebas 21 JUnit: Procedimiento  Antes de implementar una determinada funcionalidad.junit. repite el ciclo: piensa en cómo probarla. vendría muy bien algo que nos permitiera definir sistemáticamente una serie de pruebas y ejecutarlas automáticamente. ejecuta todas las pruebas que hiciste (nuevas y viejas). Lo vemos con un ejemplo.

hasta que //desarrollemos el método } } Documentación y Pruebas 23 JUnit: Ejemplo (2) ¿Qué pruebas pueden hacerse?  Caso normal: array con valores cualesquiera  [3. 9] -> 9  El mayor número está duplicado en el array  [9. 8] -> 9  El mayor número se encuentra al principio o al final de la lista  [9. 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. 7. -6. 7. 8] -> 9  [8. -22] -> -4 Documentación y Pruebas 24 12 . 7. 7. 8] -> 9  Sólo hay un elemento en el array  [7] -> 7  Array compuesto por números negativos  [-4. -7. 9. 9. // para que compile. 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.

indice < lista. 9. 8})). 9. } public void testSoloUno() { assertEquals(7. MayorNumero. assertEquals(9. 8})).framework. -7. MayorNumero. 7.mayorNumero(new int[] {-4.textui. 7. 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. } } return max. MayorNumero. } public void testOrden() { assertEquals(9. MayorNumero.length-1. 9. 7.*.mayorNumero(new int[] {3. assertEquals(9. max = Integer. indice++) { if (lista[indice] > max) { max = lista[indice]. public class TestMayorNumero extends TestCase { public TestMayorNumero() { } public void testSimple() { assertEquals(9.mayorNumero(new int[] {7.MAX_VALUE.mayorNumero(new int[] {9. 8})).mayorNumero(new int[] {9. MayorNumero. -6. } public void testDuplicados() { assertEquals(9. for (indice = 0. } } Documentación y Pruebas 26 13 . 9})).mayorNumero(new int[] {7})). 22})). } public static void main (String args[]) { junit. } public void testTodosNegativos() { assertEquals(-4. MayorNumero.class).mayorNumero(new int[] {7. 8})). MayorNumero.TestRunner. } Documentación y Pruebas 25 JUnit: Ejemplo (4) Escribimos el código de las pruebas: import junit.run(TestMayorNumero. 8.

TestRunner.run(<clase>) Documentación y Pruebas 28 14 .textui. 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 27 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.

en cuanto falle uno de los métodos de comprobación se para la ejecución. Objeto real)  Comprueba que son la misma referencia  assertNotSame (Objeto esperato. Junit: comprobaciones  assertEquals (valor_esperado. valor_real). 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 29 Junit: Uso de las comprobaciones  En una función de prueba (“testXXX”). Esta es la utilidad del método fail.  En ese caso.  Los valores pueden ser de cualquier tipo  Si son arrays.  A la hora de ejecutar la función prueba (“testXXX”).  En general hay que comprobar que un método lanza todas las excepciones que se han declarado en el mismo cuando debe. No se ejecutan el resto de métodos de comprobación tras el que falló. public void testExcepcionOrdenarListaNula( ) { try { ordena_lista(null). } catch (RuntimeException e) { } } Documentación y Pruebas 30 15 . antes de seguir es MUY aconsejable corregir el fallo que se ha producido. Y que no las lanza cuando no hay motivo para ello. se pueden poner tantos métodos de comprobación como sean necesarios para implementar el caso de prueba concreto. no se comprueban elemento a elemento. fail(“Debería haber lanzado una excepción”). sólo la referencia  assertTrue (condición_booleana)  assertFalse (condición_booleana)  assertSame (Objeto esperado.

... Junit: setUp & tearDown  Se pueden poner métodos para envolver las pruebas: public void setUp() { . } setUp() setUp() setUp() test001() test002() test003() tearDown() tearDown() tearDown() Documentación y Pruebas 31 16 .... } public void tearDown() { .