El concepto de JUnit Parameterized Test es un concepto relativamente nuevo y pertenece a JUnit 5. Cuando realizamos pruebas unitarias en muchas ocasiones nos encontramos con la necesidad de realizar el mismo test pasando diferentes grupos de parámetros. Vamos a ver un ejemplo sencillo de cómo esto funciona. El primer paso que deberemos hacer es construir un proyecto Maven y con él añadir las dependencias necesarias de Junit para crear JUnit Parameterized Test.
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params --> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.9.0</version> <scope>test</scope> </dependency>
Una vez realizado este primer paso el siguiente paso es actualizar el proyecto de Maven para que por lo menos trabaje con Java 1.8.
<properties> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> </properties>
Hemos terminado de configurar el proyecto es momento de construir código y generar unas pruebas unitarias elementales. Para ello nos vamos a apoyar en la clase Nota . Esta clase se encarga de definir el concepto de nota y de devolvernos una calificación concreta dependiendo de la Nota que tengamos.
package com.arquitecturajava.models;
import java.util.Objects;
public class Nota {
private String asignatura;
private double valor;
public String getAsignatura() {
return asignatura;
}
public void setAsignatura(String asignatura) {
this.asignatura = asignatura;
}
public double getValor() {
return valor;
}
public void setValor(double valor) {
if (valor<0 || valor>10) throw new RuntimeException("valor de nota no valido");
this.valor = valor;
}
public Nota(String asignatura, double valor) {
super();
this.setAsignatura(asignatura);
this.setValor(valor);
}
public String getCalificacion() {
// sacame un mensaje cuando sea menor de cero
// o mayor de 10
if (valor>=0 && valor<=3) {
return "MuyDeficiente";
}else if (valor>3 && valor<5) {
return "Insuficiente";
}else if (valor>=5 && valor<6) {
return "Suficiente";
}else if (valor>=6 && valor<7) {
return "Bien";
}else if (valor>=7 && valor<9) {
return "Notable";
}else return "SobreSaliente";
}
@Override
public int hashCode() {
return Objects.hash(asignatura, valor);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Nota other = (Nota) obj;
return Objects.equals(asignatura, other.asignatura)
&& Double.doubleToLongBits(valor) == Double.doubleToLongBits(other.valor);
}
}
La clave en este código la tenemos en el método getCalificacion().
Este método dependiendo del valor de la Nota nos devuelve Insuficiente, Notable etc.
public String getCalificacion() {
// sacame un mensaje cuando sea menor de cero
// o mayor de 10
if (valor>=0 && valor<=3) {
return "MuyDeficiente";
}else if (valor>3 && valor<5) {
return "Insuficiente";
}else if (valor>=5 && valor<6) {
return "Suficiente";
}else if (valor>=6 && valor<7) {
return "Bien";
}else if (valor>=7 && valor<9) {
return "Notable";
}else return "SobreSaliente";
} Usando JUnit Parameterized Test
Vamos a construir una prueba unitaria que nos permite Testear cuando uno nota es MuyDefiente . Es decir se encuentra ubicada entre 0 y 3.
package com.arquitecturajava.models;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
public class NotaTest2 {
@Test
public void muyDeficienteTestSencillo() {
Nota nota = new Nota("matematicas",2);
String calificacion= nota.getCalificacion();
assertEquals("MuyDeficiente",calificacion);
}
}
Este test es funcional pero en muchos casos nos interesará validar también los limites de la Nota. En este caso que los valores sean 0 o 3. Añadimos más código al test
@Test
public void muyDeficienteTestSencillo() {
Nota nota = new Nota("matematicas",2);
String calificacion= nota.getCalificacion();
assertEquals("MuyDeficiente",calificacion);
Nota nota2 = new Nota("matematicas",2);
String calificacion2= nota2.getCalificacion();
assertEquals("MuyDeficiente",calificacion2);
Nota nota3 = new Nota("matematicas",2);
String calificacion3= nota3.getCalificacion();
assertEquals("MuyDeficiente",calificacion3);
} Test y Limitaciones
El Test nos es más práctico ya que valida los límites del valor . Sin embargo hay que escribir mucho más código para llegar a esa situación . En principio no nos puede parecer preocupante , pero cuando tengamos muchos Test será más código que leer. Podemos simplificar este código con un JUnit Parameterized Test que nos permite asociar a la prueba unitaria unos parámetros y pasárselos al método a través de una variable.
package com.arquitecturajava.models;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
public class NotaTest2 {
@ParameterizedTest
@DisplayName("Nota insuficiente valor:2 standar valor: 0,3 limites nota")
@ValueSource (doubles= {2,0,3})
public void muyDeficienteTest(double valorNota) {
Nota nota2 = new Nota("matematicas",valorNota);
String calificacion= nota2.getCalificacion();
assertEquals("MuyDeficiente",calificacion);
}
}
@ParameterizedTest
En este caso hemos usado la anotación @ParameterizedTest y @ValueSource para parametrizar el test y que reciba un parámetro con diversos valores.
Esto reduce el código de forma significativa y nos permite tener unas pruebas unitarias mucho más compactas.