Maven y junit

De ChuWiki


Integración de Maven y JUnit[editar]

Cuando estamos desarrollando código, más importante que hacer test de nuestro código, es ejecutar esos test con frecuencia, de forma automática. Maven tiene esto en cuenta y si hacemos test de JUnit y los ponemos en el lugar adecuado de nuestro proyecto, Maven los localizará y ejecutará automáticamente cada vez que compilemos.

Vemos los detalles

Dependencia de JUnit[editar]

En el fichero pom.xml de nuestro proyecto debemos poner la dependencia de JUnit. Puede ser algo como esto

<project>
   ...
   <dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.13.2</version>
			<scope>test</scope>
		</dependency>
        ...
   </dependencies>
   ...
</project>

Es importante poner el <scope> como test. Esto hará que las clases de JUnit no estén accesibles en nuestro proyecto. Maven sólo las tendrá en cuenta para ejecutar los test. Y nos dará error de compilado si en el código de nuestro proyecto intentamos usar clases de la librería JUnit.

Estamos usando en el ejemplo la última versión de JUnit 4. Hay una versión nueva, JUnit 5.x.x que es algo más compleja de usar. Por eso, ponemos aquí la versión 4.

Directorio src/test/java[editar]

En Maven, por defecto, los fuentes de nuestro proyecto deben estar en el directorio src/main/java. Para los test, el directorio adecuado es src/test/java. En ese directorio podemos poner nuestras clases de test y en ellas tendremos accesibles las anotaciones y clases de la librería JUnit.

Es importante que nuestras clases de test comienzen su nombre por Test... o bien terminen su nombre en ...Test, ...Tests o ...TestCase. Esto hace que Maven las identifique como clases con test a ejecutar

Un ejemplo de test en este directorio de fuentes puede ser el siguiente

...
import org.junit.Assert;
import org.junit.Test;
...

public class CalculatorTest {
    @Test
    public void mustAdd (){
        Assert.assertEquals("Add test", 4, Calculator.add(2,2));
    }

    @Test
    public void mustSubstract(){
        Assert.assertEquals("Substract test", 3, Calculator.substract(6,3));
    }

    @Test
    public void mustMultiply(){
        Assert.assertEquals("Multiply test", 6, Calculator.multiply(2,3));
    }

    @Test
    public void mustDivide(){
        Assert.assertEquals("Divide test", 3, Calculator.divide(6,2));
    }
}

Es un test de JUnit simple, para una calculadora simple. Cada uno de los métodos de test va anotado con @Test, que es una anotación propia de JUnit. Maven detectará estas anotaciones en las clases de test del directorio src/test/java y las ejecutará como test de Junit.

Ejecutar los test de JUnit con Maven[editar]

El comando maven

mvn test

ejecuta todos los test que encuentre en src/test/java. En nuestro ejemplo, una parte de la salida del comando maven puede ser esta

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.chuidiang.ejemplos.junit45.CalculatorTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 sec

Results :

Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

Vemos que ha ejecutado 4 test de CalculatorTest y que no ha fallado ninguno.

Los test no se ejecutarán sólo con el comando mvn test. Se ejecutarán con cualquier comando Maven que sea de una fase superior. En concreto, no se ejecutará con mvn compile, pero sí se ejecutará con mvn package, mvn verify, mvn install y mvn deploy. Y esto es lo que hace interesante integrar los test de JUnit en Maven, que se ejecutarán cada vez que queramos generar el jar de nuestro proyecto.

Ejecutar/Excluir test de JUnit individuales[editar]

Podemos ejecutar test individualmente poniendo la opción -Dtest=. Esta opción admite expresiones complejas. Veamos algunos ejemplos

mvn test -Dtest=CalculatorTest

Buscará una clase que se llame CalculatorTest dentro del directorio src/test/java, da igual en qué paquete esté, y la ejecutará como test de JUnit.

mvn test -Dtest=!CalculatorTest

La hemos precedido con !. Eso hará que se ejecuten todos los demás test menos este.

mvn test -Dtest=CalculatorTest#mustAdd

Al añadir detrás #mustAdd siendo mustAdd el nombre de uno de los metodos de test, Maven sólo ejecutará ese método de esa clase.

mvn test -Dtest=!CalculatorTest#mustAdd

Nuevamente, precediendo con !, se ejecutará todos los test de todas las clases de test... excepto este método concreto

mvn test "-Dtest=CalculatorTest#mustAdd, CalculatorTest#mustSubstract"

Fíjate que hemos metido entre comillas dobles toda la opción -Dtest=.... Así podemos poner, separados por comas y un espacio, varios patrones de test. El comando del ejemplo ejecutará sólo esos dos métodos e ignorará los demás métodos de esa clase, así como todas las demás clases de test.

Saltar los test[editar]

Si por el motivo que sea no nos interesa que se ejecuten los test, basta ejecutar el comando maven que nos interese con una de estas opciones: -DskipTests o -Dmaven.test.skip=true. Por ejemplo

mvn install -DskipTests

En maven skip tests puedes ver algún detalle adicional.

Informe de los test JUnit[editar]

Al ejecutar los test, en el directorio target/surefire-reports nos aparecerán unos ficheros con los resultados de los test. Por cada clase de test, aparecen dos ficheros, uno en formato txt y el otro en formato xml. Ambos tienen el resultado de los test y el detalle del fallo, si lo ha habido.

Podemos sacar también un informe html más vistoso. El comando

mvn surefire-report:report

genera en target/site/surefire-report.html una página html como la de la siguiente imagen

Informe html de Maven con los resultados de JUnit
Informe html de Maven con los resultados de JUnit

En ella hay un resumen de todos los test que se han ejecutado o no ejecutado. Un icono indica si se han pasado correctamente o no. Y en caso de fallo se puede expandir el fallo para ver el detalle.

Es posible generar un informe de cobertura de los test para ver qué partes de nuestro código han sido probaas por nuetros test y cuales no. Esto nos permite ampliar el conjunto de test sabiendo qué partes del código faltan por cubrir.