Creación: 27-06-2011
Índice de contenidos
1. Introducción
2. Entorno
3. Como usar ClasspathSuite
3.1. Descargar el jar de ClasspathSuite
3.2. Crear un nuevo proyecto y añadir el jar de ClasspathSuite
3.3. Añadir los proyectos de los que queremos lanzar todos los test
3.4. Como ejecutar todos los test de todos los proyectos
4. Conclusiones
5. Sobre el autor
1. Introducción
Todos los que estamos acostumbrados a trabajar en Eclipse, seguro que estamos hartos de posicionarnos sobre un proyecto y hacer Botón derecho –> Run As –> JUnit Test (o su
equivalente CMD+ALT+X T), para ejecutar todos los test de JUnit que se encuentran dentro de ese proyecto.
Pero es bastante común y buena práctica tener más de un proyecto, ya que una misma aplicación la separamos en varios módulos. Si además de esto trabajamos con TDD
tendremos un número considerable de test, y las buenas prácticas nos dicen que debemos ejecutar todos los test cada vez. Donde todos significa todos, es decir, los test de todos los
proyectos y no sólo los test del proyecto donde hemos tocado código (es cierto que si los test son unitarios no deberían afectar a otros módulos, pero más vale prevenir que curar, y por eso lo llaman buenas prácticas 😉
Pero ¿en Eclipse es posible ejecutar de golpe todos los test de todos los proyectos? Lamentablemente la respuesta es NO, ni siquiera en la última versión Eclipse Indigo.
En este tutorial vamos a ver precisamente eso, como gracias a ClasspathSuite podemos ejecutar todos los test de JUnit de todos los proyectos de nuestro workspace.
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil MacBook Pro 17′ (2.8 GHz Intel i7, 8GB DDR3 SDRAM, 256GB Solid State Drive).
- NVIDIA GeForce GT 330M with 512MB
- Sistema Operativo: Mac OS X Snow Leopard 10.6.8
- Eclipse 3.7, codename Indigo
- JUnit 4.8.2
- ClasspathSutie 1.2.5
3. Como usar ClasspathSuite
ClasspathSuite es un simple jar con un Runner de JUnit. Este Runner se encarga de buscar todos los test JUnit por el classpath y ejecutarlos.
Con esta idea, el mecanismo para ejecutar los test de todos los proyectos es sencillo, simplemente tenemos que crear un nuevo proyecto Java donde añadiremos como dependencia el resto de proyectos (todos aquellos proyectos de los que queremos lanzar los test de JUnit).
Así, supongamos que tenemos dos proyectos: modulo-a y modulo-b. Donde cada uno de ellos tiene sus respectivos test.
3.1. Descargar el jar de ClasspathSuite
Lo primero que vamos ha hacer es descargarnos el jar de ClasspathSuite. Para ello vamos a la página ClasspathSuite y elegimos la versión que nos interese (en mi caso cpsuite-1.2.5-jar, que es para JUnit 4.5).
3.2. Crear un nuevo proyecto y añadir el jar de ClasspathSuite
Ahora vamos a crear un nuevo proyecto Java, para ello hacemos File –> New –> Java Proyect
Pulsamos el botón Finish para terminar la creación del proyecto.
Ahora vamos a añadir el jar de ClasspathSuite al proyecto que acabamos de añadir. Para ello hacemos botón derecho sobre el proyecto recién creado y nos vamos a Properties (también lo podemos hacer con CMD+I sobre el proyecto). Nos posicionamos en la izquierda sobre la opción Java Build Path, y luego en la pestaña Libraries.
Pulsamos el botón de Add External JARs… e indicamos la ruta donde nos hemos descargado el jar. Ahora deberíamos ver el jar en nuestra lista de librerías.
Pulsamos el botón OK para aceptar los cambios.
3.3. Añadir los proyectos de los que queremos lanzar todos los test
Ya tenemos creado el proyecto y añadida la librería. Ahora tenemos que marcar como dependencias todos los proyectos de los que queremos lanzar todos los test. Igual que antes hacemos Botón Derecho sobre el proyecto –> Propiedades –> Java Build Path –> Pestaña Projects, y añadimos (botón Add…) todos los proyectos (en nuestro ejemplo: modulo-a y modulo-b).
3.4. Como ejecutar todos los test de todos los proyectos
Ahora en nuestro nuevo proyecto basta con crear un test de la siguiente forma:
import org.junit.extensions.cpsuite.ClasspathSuite; import org.junit.runner.RunWith; @RunWith(ClasspathSuite.class) public class RunAllTest { }
Vemos como la clase está vacía, no define ningún test. Lo interesante está en la línea 4, donde le decimos que use el runner ClasspathSuite.class. Este es el que se encarga de buscar y ejecutar todos los test en los proyectos de los que depende.
Si ejecutamos esta clase de test (Sobre la clase ALT+CMD+X T, o botón derecho Run As –> JUnit Test) obtendremos el siguiente resultado:
Se ve claramente como se han ejecutado los test de ambos proyectos (he renombrado los proyectos y los test respecto a la primera imagen para que se vea más mejor como se han ejecutado todos los test).
3.5. Ejecutando los test unitarios y los test de integración por separado
Dentro del desarrollo de una aplicación es normal que tengamos muchos test unitarios y unos pocos de integración. El problema que tienen estos últimos es que requieren configurar el entorno (levantar el contexto de Spring, preparar una base de datos, …) por lo que suelen tardar más en ejecutarse; mientras que los test unitarios suele ser cuestión de unos pocos milisegundos.
Con lo que hemos visto en el punto anterior, constantemente estamos lanzando todos los test, por lo que se puede hacer una tarea aburrida ya que tenemos que esperar a que terminen los test de integración. Y esta situación suele desembocar en que dejamos de lanzar los test o por lo menos no los lanzaremos todo lo que deberíamos (cada vez que hacemos cualquier cambio, incluso si cambiamos un comentario 😉
Pero no preocuparse porque ClasspathSuite viene preparado para todo y nos va a permitir realizar filtros. De esta forma si queremos ejecutar sólo los test unitarios podríamos hacernos una clase del estilo:
package com.autentia.asefa; import org.junit.extensions.cpsuite.ClasspathSuite; import org.junit.extensions.cpsuite.ClasspathSuite.ClassnameFilters; import org.junit.runner.RunWith; @RunWith(ClasspathSuite.class) @ClassnameFilters({ "!.*IntegrationTest" }) public class AllUnitTestRunner { }
Mientras que si queremos lanzar sólo los test de integración podemos hacernos una clase del estilo:
package com.autentia.asefa; import org.junit.extensions.cpsuite.ClasspathSuite; import org.junit.extensions.cpsuite.ClasspathSuite.ClassnameFilters; import org.junit.runner.RunWith; @RunWith(ClasspathSuite.class) @ClassnameFilters({ ".*IntegrationTest" }) public class AllIntegrationTestRunner { }
La gracia de los dos ejemplos está en la línea 08, donde se ve como con la anotación @ClassnameFilters podemos definir una serie de filtros para indicar a ClasspathSuite las clases de test que tiene que tener en cuenta.
En nuestro ejemplo estamos tomando la convención de llamar a las clases de test de integración con el sufijo IntegrationTest, de esta forma con la primera clase y la admiración «!» estamos negado que se ejecuten estas clases, mientras que en la segunda clase sólo estamos ejecutando estas clases.
Para más información sobre qué cosas se pueden hacer con ClasspathSuite os recomiendo una visitar a su página donde explica algunos truquitos más.
4. Conclusiones
Después de este tutorial ya no hay excusa para no estar ejecutando constantemente nuestro test, sobre todos los unitarios que se ejecutan en cuestión de milisegundos.
Además para facilitar esto os recomiendo ir a las preferencias del Eclipse: En el menú, Eclipse –> Preferences… –> Run/Debug –> Launching –> Launch Operation, y marcar activa la opción de Always launch the previously launched application.
De esta forma una vez ejecutéis la clase que lanza todos los test unitarios de todos los proyectos, podéis hacer CMD+SHIFT+F11 y, con independencia del fichero sobre el que os encontréis, estaréis lanzando de nuevo todos los test. Así nuestro ciclo de trabajo será:
- hacer un cambio,
- CMD+S (Guardar),
- CMD+SHIFT+F11 (Lanzar todos los test unitarios),
- si todo va bien, volver al primer punto
5. Sobre el autor
Alejandro Pérez García, Ingeniero en Informática (especialidad de Ingeniería del Software) y Certified ScrumMaster
Socio fundador de Autentia (Desarrollo de software, Consultoría, Formación)
mailto:alejandropg@autentia.com
Autentia Real Business Solutions S.L. – «Soporte a Desarrollo»