jueves, 6 de junio de 2013

Tutorial sobre JUnit

1 - Introducción y vista general
JUnit es un framework de programación para escribir tests de unidad fácilmente repetibles. Se enmarca dentro de la arquitectura xUnit de frameworks de testeo (Existen AUnit, CUnit, NUnit, ... para otros lenguajes de programación). Dentro de los diferentes tipos de pruebas que se realizan sobre una aplicación en desarrollo, JUnit se dedica a las pruebas unitarias, llamadas así porque testean funcionalidades concretas del código. Son pruebas, podría decirse, locales, enfocadas a la funcionalidad de métodos o clases. JUnit nos ahorra tiempo de testeo de software porque nos evita repetir un montón de pruebas de forma manual cada vez que alguna modificación en el código así lo requiere.

El código creado con JUnit normalmente va en carpeta aparte para no mezclarse con el código propio de la aplicación. En su versión actual, la 4, se utilizan anotaciones en el código de testeo que identifican los métodos que realizan las pruebas. Los métodos de test están normalmente en una clase (clase de testeo) sólo para este fin. El orden de los métodos de test no es tomado en cuenta por JUnit (que lo considera arbitrario) así que un test no debería depender de otros.

Las anotaciones antes mencionadas que están disponibles en JUnit 4 son las siguientes (traducidas de [2]):


Annotation Description
@Test
public void method()
La anotación @Test identifica que un método es un método de test.
@Before
public void method()
Este método es ejecutado antes de cada test. Este método puede preparar el entorno de test (por ejemplo, leer datos de entrada o inicializar la clase).
@After
public void method()
Este método es ejecutado después de cada test. Este método puede limpiar el entorno de test (por ejemplo, borrar datos temporales o restablecer valores por defecto). También puede recuperar memoria, limpiando estructuras de memoria costosas.
@BeforeClass
public static void method()
Este método es ejecutado una vez, antes del comienzo de todos los tests. Se puede usar para realizar actividades intensivas en cuanto al tiempo, por ejemplo para conectarse a una base de datos. Los métodos así anotados necesitan ser definidos como static en JUnit.
@AfterClass
public static void method()
Este método es ejecutado una vez, después de que todos los tests hayan sido finalizados. Esto puede usarse para realizar tareas de limpieza, por ejemplo, desconectarse de una base de datos. Los métodos así anotados necesitan ser definidos como static en JUnit.
@Ignore Ignora el método de test. Esto es útil cuando el código subyacente ha sido cambiado y el caso de testeo no ha sido adaptado. O si el tiempo de ejecución de este test es demasiado largo como para ser incluido.
@Test (expected = Exception.class) Falla si el método no lanza la excepción esperada.
@Test(timeout=100) Falla si el método toma más de 100 milisegundos.

Dentro de los métodos de testeo escritos usando JUnit, se usan las llamadas sentencias de aserción (assert). Esto quiere decir que JUnit proporciona métodos estáticos en la clase Assert que nos permiten comprobar si se cumplen las condiciones que decidamos fijar. Estos métodos suelen empezar con la palabra assert y nos permiten especificar el mensaje de error si no se cumple la aserción y el valor esperado. En una aserción se compara dicho valor esperado con el que realmente se produce en la ejecución. Si no coinciden, se lanza una AssertionException. Hay varios métodos de aserción que pueden consultarse en la documentación de la API. Por poner un ejemplo, nombremos assertTrue([mensaje], boolean condicion) que comprueba si se cumple la condición booleana suministrada.

La instalación de JUnit en el caso general es simple, ya que consiste en descargar la biblioteca de JUnit en formato .jar desde la página web oficial de JUnit (http://junit.org/) y añadirla luego a nuestro proyecto java y al classpath. En el caso concreto de que usemos el IDE Eclipse, nos encontraremos con que JUnit viene ya integrado.

En cuanto a la ejecución de las pruebas unitarias, los tests pueden ejecutarse de forma integrada con la interfaz del IDE si estamos trabajando en Eclipse, pero también puede hacerse de forma independiente (para este u otros IDE) usando el método runClasses() de la clase org.junit.runner.JUnitCore. Cabe decir también que para facilitar la ejecución de varias clases de testeo, haciendo que todas se ejecuten de forma conjunta, estas pueden combinarse en lo que en JUnit se llama “suite de pruebas” (test suite).

JUnit dispone también de opciones avanzadas que van más allá de lo que va a cubrir este tutorial introductorio, no obstante las nombraremos: los tests parametrizados, las reglas (anotación @Rule para mayor flexibilidad en los tests) y los falsos objetos (Docking).

2 - Ejemplo de uso con Eclipse

Para este tutorial introductorio vamos a trabajar con Eclipse pues este IDE tiene soporte integrado para JUnit y nos facilita el trabajo. Sin embargo, los tests JUnit pueden escribirse manualmente de forma independiente en cualquier IDE.

Este tutorial va a consistir en lo siguiente: crearemos un proyecto java en Eclipse y en este definiremos una clase Operaciones.java, que es el código sobre el que vamos a realizar las pruebas de unidad. Esta clase va a ser de funcionalidad simple pues vamos a definir las cuatro operaciones básicas sobre enteros: suma, resta, multiplicación y división, donde la división la programaremos aposta con una funcionalidad equivocada. Para esta clase crearemos nuestra clase de testeo ClaseTest.java que tendrá cuatro métodos para comprobar cada uno de los de la clase Operacion. Finalmente ejecutaremos las pruebas de unidad para mostrar la simplicidad de la prueba y la facilidad de repetirla ante futuros cambios en el código sobre el que realizamos las pruebas. Los pasos serán (1) crear el proyecto java, (2) programar la clase Operacion.java, (3) definir sobre ella la clase de test ClaseTest.java y finalmente (4) ejecutar las pruebas de unidad:

1) Creamos un nuevo proyecto Java (File->New->Project…)


Al que llamaremos TutorialJUnit y pulsamos Next>
Con “Create new source folder” crearemos una carpeta de nombre test, donde luego irá la clase de test


2) En la carpeta src creamos la clase Operaciones.java

Que tiene el siguiente código (notar nuestra “equivocación” en el método dividir):

3) Y ahora creamos la clase de test sobre la anterior. Usamos para ello el asistente que nos da Eclipse:
En el asistente indicamos los siguientes datos:
Tras pulsar a Next> seleccionamos los métodos sobre los que queremos realizar pruebas de unidad:
Eclipse piensa en todo…
Y aquí tenemos la plantilla de tests que deberemos modificar para cubrir nuestras necesidades:
La modificamos así (hemos hecho comprobaciones simples pero aún así de utilidad):
4) Sobre la clase de pruebas, hacemos click con el botón derecho y ejecutamos como JUnit Test

Y nos aparece una nueva pestaña de Eclipse donde se nos muestran los resultados de las pruebas. Como nos esperábamos, hemos encontrado un fallo en los tests. Se ha detectado que el funcionamiento del método dividir no era el esperado, como ya sabíamos por haber programado este método aposta de forma equivocada:

3 - Bibliografía y referencias

[1] Página web oficial de JUnit (en http://junit.org/)
[2] Tutorial de JUnit de Lars Vogel (en http://www.vogella.com/articles/JUnit/article.html)
[3] http://es.wikipedia.org/wiki/JUnit
[4] http://en.wikipedia.org/wiki/JUnit

 4 - Autores

Diego Jesús y Francisco

3 comentarios:

  1. Buenas tardes. Gracias por su ejemplo pues hizo lo que en varias paginas no pude encontrar... un ejemplo claro y sin "lagunas" u omisiones que muchas veces nos dejan mas confundidos que como estabamos al principio haha

    ResponderEliminar
  2. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  3. Hola, tengo una gran duda: ¿qué tan difícil podría ser desarrollar un app java para celulares (de los antiguos no android) para obtener internet por medio del cable usb o bluetooth de otro dispositivo (laptop o celular)? Al no encontrar librerías relacionadas no tengo idea de por dónde empezar, gracias.

    ResponderEliminar