JUnit4 integracion con Maven2 y Spring


Introducción a JUnit
JUnit es un conjunto de clases para hacer pruebas unitarias de aplicaciones Java, permite realizar la ejecución de clases Java de maneta controlada, para poder evaluar si el funcionamiento de cada uno de los métodos de la clase se comporta como se espera dependiendo de algún valor de entrada y un retorno esperado. Si la clase cumple con el valor que se supone es el correcto el JUnit devolverá que el método de la clase paso exitosamente la prueba, en caso contrario el JUnit devolverá un fallo en el método correspondiente.

Anotaciones JUnit4:
  • @Test : Indica cual es el caso de prueba
  • @Ignore: Se utiliza para deshabilitar el caso de prueba
  • @Before: Es el código que se utiliza antes de cada caso de prueba
  • @After: Es el código que se ejecuta después de cada caso de prueba
Uso de JUnit4 con Maven y Spring
La formación de nuestras carpetas seria la siguiente:
Tenemos en la parte de main las clases que serán compiladas y que serán utilizadas en la aplicación, estas son las clases que queremos probar que funcionen adecuadamente. En este caso tenemos una interfase llamada OrdenaStrategy la cual tiene una función para ordenar un array de enteros, y tenemos 2 implementaciones diferentes para esta interfase las cuales son diferentes algoritmos para el ordenamiento del arreglo. En la carpeta de test tenemos los JUnits de las clases anteriores, para que estos JUnit funcionen el nombre tiene que terminar con Test para que sean cargados, por convención se colocan los JUnits en el mismo paquete que están las clases que se quieren probar y con el mismo nombre pero terminación Test. En la parte de test/resources se alojan los archivos de configuración de spring para cada JUnit, estos archivos serán cargados por los JUnits antes de la ejecución de los casos de prueba, en estos archivos se configuran los beans necesarios para que la clase que se quiere probar funcione correctamente, por default los archivos son cargados automáticamente con el nombre del JUnit concatenado con -context.
Lo primero que tenemos que hacer es agregar la configuración de nuestro pom.xml, en el cual agregamos las dependencias que tenemos que utilizar. Utilizamos para este ejemplo la versión de Spring 3 con la versión de JUnit 4.8, agregándole la configuración para que maven compile con la versión 1.6 de Java
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.blogspot.appcode</groupId> <artifactId>tutorial-junit</artifactId> <version>1.0.0</version> <name>Tutorial JUnit</name> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${org.springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${org.springframework.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build> <properties> <org.springframework.version>3.0.5.RELEASE</org.springframework.version> <junit.version>4.8.2</junit.version> </properties> </project>
Ahora creamos nuestros clases.
OrdenaStrategy.java
package com.blogspot.appcode.tutorial.junit; public interface OrdenaStrategy { int[] ordenar(int[] array); }
OrdenaStrategyBurbujaImpl.java
package com.blogspot.appcode.tutorial.junit.impl; import com.blogspot.appcode.tutorial.junit.OrdenaStrategy; public class OrdenaStrategyBurbujaImpl implements OrdenaStrategy { public int[] ordenar(int[] array) { int j, t; for (int i = 0; i < array.length - 1; i++) for (j = 0; j < array.length - 1; j++) if (array[j] > array[j + 1]) { t = array[j]; array[j] = array[j + 1]; array[j + 1] = t; } return array; } }
OrdenaStrategyQickSortImpl.java
package com.blogspot.appcode.tutorial.junit.impl; import com.blogspot.appcode.tutorial.junit.OrdenaStrategy; public class OrdenaStrategyQuickSortImpl implements OrdenaStrategy { public int[] ordenar(int[] array) { quickSort(array, 0, array.length - 1); return array; } private void quickSort(int array[], int low, int n) { int lo = low; int hi = n; if (lo >= n) return; int mid = array[(lo + hi) / 2]; while (lo < hi) { while (lo < hi && array[lo] < mid) lo++; while (lo < hi && array[hi] > mid) hi--; if (lo < hi) { int T = array[lo]; array[lo] = array[hi]; array[hi] = T; } } if (hi < lo) { int T = hi; hi = lo; lo = T; } quickSort(array, low, lo); quickSort(array, lo == low ? lo + 1 : lo, n); } }
Ahora creamos nuestros JUnit para probar las clases que creamos previamente con su archivo de configuración de spring.
OrdenaStrategyBurbujaImplTest.java
package com.blogspot.appcode.tutorial.junit.impl; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.blogspot.appcode.tutorial.junit.OrdenaStrategy; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class OrdenaStrategyBurbujaImplTest { @Autowired OrdenaStrategy ordenaStrategy; private int[] array; @Before public void before() { array = new int[10]; array[0] = 2; array[1] = 6; array[2] = 1; array[3] = 8; array[4] = 4; array[5] = 3; array[6] = 9; array[7] = 7; array[8] = 0; array[9] = 5; } @Test public void ordenarTest() { int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; Assert.assertArrayEquals(a, ordenaStrategy.ordenar(array)); } }
OrdenaStrategyBurbujaImplTest-context.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean class="com.blogspot.appcode.tutorial.junit.impl.OrdenaStrategyBurbujaImpl" /> </beans>
OrdenaStrategyQuickSortImplTest.java
package com.blogspot.appcode.tutorial.junit.impl; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.blogspot.appcode.tutorial.junit.OrdenaStrategy; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class OrdenaStrategyQuickSortImplTest { @Autowired OrdenaStrategy ordenaStrategy; private int[] array; @Before public void before() { array = new int[10]; array[0] = 2; array[1] = 6; array[2] = 1; array[3] = 8; array[4] = 4; array[5] = 3; array[6] = 9; array[7] = 7; array[8] = 0; array[9] = 5; } @Test public void ordenarTest() { int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; Assert.assertArrayEquals(a, ordenaStrategy.ordenar(array)); } }
OrdenaStrategyQuickSortImplTest-context.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean class="com.blogspot.appcode.tutorial.junit.impl.OrdenaStrategyQuickSortImpl" /> </beans>
Con la anotación @RunWith(SpringJUnit4ClassRunner.class) le decimos a nuestro JUnit que corra con la integración que tiene spring-test, y con la anotación @ContextConfiguration le decimos que busque un archivo que tenga el mismo nombre que la clase pero con terminación –context para que inicialice el contexto de Spring automáticamente, esta ultima anotación tiene el parámetro locations el cual es un arreglo de Strings donde le ponemos la ruta de los archivos de configuración de Spring para ser cargados. Para esto ultimo presento un ejemplo de un JUnit donde le indicamos los archivos de configuración a ser tomados, si el archivo de configuración no se encuentra en el mismo paquete, hay que indicar el contextpath de donde va a tomar el archivo de configuración de Spring.
package com.blogspot.appcode.tutorial.junit.impl; import java.util.Date; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.blogspot.appcode.tutorial.junit.impl.OrdenaStrategyBurbujaImpl; import com.blogspot.appcode.tutorial.junit.impl.OrdenaStrategyQuickSortImpl; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "OrdenaStrategyBurbujaImplTest-context.xml", "classpath:com/blogspot/appcode/tutorial/junit/impl/OrdenaStrategyQuickSortImplTest-context.xml" }) public class OrdenaStrategyCompareTest { @Autowired OrdenaStrategyBurbujaImpl ordenaBurbuja; @Autowired OrdenaStrategyQuickSortImpl ordenaQuickSort; private int[] array; @Before public void before() { array = new int[10]; array[0] = 2; array[1] = 6; array[2] = 1; array[3] = 8; array[4] = 4; array[5] = 3; array[6] = 9; array[7] = 7; array[8] = 0; array[9] = 5; } @Test public void ordenaBurbujaTest() { int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; long time1 = new Date().getTime(); int[] burbuja = ordenaBurbuja.ordenar(array); long time2 = new Date().getTime(); System.out.println("Tiempo: " + (time2 - time1) + " ms"); Assert.assertArrayEquals(a, burbuja); } @Test public void ordenaQuickSortTest() { int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; long time1 = new Date().getTime(); int[] quickSort = ordenaQuickSort.ordenar(array); long time2 = new Date().getTime(); System.out.println("Tiempo: " + (time2 - time1) + " ms"); Assert.assertArrayEquals(a, quickSort); } }
Para correr nuestros casos de prueba tenemos que utilizar el comando desde nuestra consola
$> mvn test
Este comando solo llega hasta el punto de test de la aplicación, si utilizáramos install también correría las pruebas ya que install compila y prueba antes de hacer el empaquetamiento, para que nuestra aplicación salte la fase de pruebas podemos realizarlo con este parámetro: mvn –Dmaven.test.skip=true, lo que nos quedaría:
$> mvn install –Dmaven.test.skip=true
Lo que pasa cuando esta en la fase de compile es que los archivos no los compila y nos divide en dos carpetas en la carpeta de target de nuestra aplicación, la carpeta de classes y la carpeta de test-classes, para la parte de test-classes, así cuando nos empaqueta la aplicación solo se empaquetan las clases que serán usadas y se descartan las clases que son utilizadas para pruebas que serian los JUnit y algunos archivos de resources y/o clases que creamos para apoyarnos a probar nuestros JUnits. En el archivo pom.xml, en la parte de dependencias, también se puede aclarar que librerías solo serán usadas para la fase de pruebas y que librerías son necesarias para nuestro proyecto por medio de la tag scope que esta dentro de la tag dependency.
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency>
Cuando maven ejecuta test lo que nos genera es que cada caso de prueba (los métodos con la anotación @Test) se ejecuten, en consola nos aparece algunos datos informativos como el tiempo que tardo en correr y nos genera un reporte de los casos de prueba de las clases. Los reportes están contenidos en la carpeta sunfire-reports dentro de nuestra carpeta target de nuestra aplicación. En esta carpeta podemos encontrar reportes en formato txt y xml con información de los casos de prueba que se ejecutaron. Cuando existe una excepción en tiempo de ejecución, nuestros reportes xml no se generaran, pero nuestros reportes txt nos dirán cual fue el error en tiempo de ejecución que ocurrió dentro de nuestro JUnit.
Puede descargar el codigo fuente de este pequeño tutorial aqui

No hay comentarios:

Publicar un comentario