🌱 Digital Garden

Search

Search IconIcon to open search

Last updated Jul 20, 2023 Edit Source

Quizas ver primero:


# Tests con Parametros en Java usando JUnit 5

Ahora que ya sabemos como escribir tests y conocemos el Ciclo de vida de un Test en Java usando JUnit 5, podemos pasar a escribir tests mas complejos y que incluyan mas funcionalidad.

Para iniciar a utilizar tests con parametros debemos importar a nuestro gestor de dependencias la libreria auxiliar para JUnit 5.

Gradle:

1
2
3
dependencies {    
	testImplementation "org.junit.jupiter:junit-jupiter-params:5.7.1"
}

Maven:

1
2
3
4
5
6
<dependency>
	<groupId>org.junit.jupiter</groupId>
	<artifactId>junit-jupiter-params</artifactId>
	<version>5.7.1</version>
	<scope>test</scope>
</dependency>

# Inicializacion

Para entender este tema, veamos un ejemplo con nuestra clase Calculator, la cual tiene el metodo maxOf para determinar el maximo de dos numeros.

1
2
3
4
5
6
7
8
9
public class Calculator {
	public int maxOf(int a, int b) {
		if (a >= b) {
			return a;
		} else {
			return b;
		}
	}
}

Ahora veamos como hariamos la clase para probarlo hasta ahora.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTests {
	@Test
	void testMaxFirstArgGreaterThanSecondArg() {
		Calculator calculator = new Calculator();
		int result = calculator.maxOf(2, 1);
		int expected = 2;
		assertEquals(expected, result);
	}

	@Test
	void testMaxFirstArgLessThanSecondArg() {
		Calculator calculator = new Calculator();
		int result = calculator.maxOf(1, 2);
		int expected = 2;
		assertEquals(expected, result);
	}

	@Test
	void testMaxFirstArgEqualToSecondArg() {
		Calculator calculator = new Calculator();
		int result = calculator.maxOf(2, 2);
		int expected = 2;
		assertEquals(expected, result);
	}
}

Ahora si, pasamos a ver las nuevas adiciones de nuestra nueva libreria.

# @ParameterizedTest

Esta anotacion nos permite indicarle a nuestro metodo que se trata de un test con parametros, por tanto, recibira los datos para su ejecucion del data source indicado. Veamos como re-escribiriamos el test anterior de forma mas simple.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.*;
class CalculatorTests {

	@ParameterizedTest
	@CsvSource({"2, 1, 2", "1, 2, 2", "1, 1, 1"})
	void testMax(int first, int second, int expected) {
		Calculator calculator = new Calculator();
		int result = calculator.maxOf(first, second);
		
		assertEquals(expected, result);
	}
}

Utilizamos la anotacion @ParameterizedTest en lugar del simple @Test. Ademas, le estamos indicando con la anotacion @CsvSource que los datos para este test seran obtenidos de los siguientes datos anotados en forma de CSV.

Adicionalmente, tambien podemos agregarle el parametro name a nuestra anotacion @ParameterizedTest para agregarle nuestro propio mensaje al momento de finalizar su ejecucion:

1
@ParameterizedTest(name = "{index} => maxOf({0}, {1}) == {2}")

# Sources para los Argumentos

Como indicamos, podemos utilizar o incluso combinar distintos data sources para los argumentos de nuestros Tests. Podemos consultar todos los disponibles en la Documentacion oficial.

# @ValueSource, @EmptySource, @NullSource y @NullAndEmptySource

Veamos algunos de sus usos, supongamos que en nuestra calculadora agregamos el metodo isEven(int n) para determinar si un numero es par o no.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.NullAndEmptySource;

import static org.junit.jupiter.api.Assertions.*;

class CalculatorTests {

	@ParameterizedTest
	@ValueSource(ints = { 0, 2, 4, 1000 })
	void testIsEven(int arg) {
		assertTrue(new Calculator().isEven(arg));
	}

	@ParameterizedTest
	@EmptySource
	void testEmpty(int[] arg) {
		assertEquals(0, arg.length);
	}

	@ParameterizedTest
	@NullAndEmptySource    
	void testNullAndEmpty(List<String> arg) {
		assertTrue(arg == null || arg.isEmpty());
	}
}

Pueden ser combinadas incluso para determinar todos los rangos de un test, desde null y empty hasta valores.

# @MethodSource

Nos permite indicar un metodo (Interno de la clase tests o externo de otra clase) la cual devuelve un parametro que nos sirve como datasource para nuestro test. Como parametro se le pasa el nombre del metodo el cual devuelve el source que nosotros esperamos recibir para probar. Cabe aclarar que estos metodos deben estar marcados con static.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

class CalculatorTests {

	@ParameterizedTest
	@MethodSource("stringFactory") 
	void testStrings(String str) {
		assertFalse(str.isEmpty());
	}

	static List<String> stringFactory() {
		return List.of("apple", "banana", "lemon", "orange");
	}
}

En caso de tener multiples parametros en el test, se debe contar devolver obligatoriamente un array, un stream, una coleccion de objetos que contengan esos parametros para que nuestro test pueda trabajar con ellos.

# @CsvSource y @CsvFileSource

Estas anotaciones nos permiten trabajar con datos que cuenten con formato CSV.

1
@CsvSource({ "apple, 5", "strawberry, 10", "cherry, 6" })
1
@CsvFileSource(resources = "/dataset.csv", numLinesToSkip = 1)

Siguiente: