Introducción a los Tests Dinámicos
Los tests dinámicos en JUnit 5 permiten la creación de tests en tiempo de ejecución. A diferencia de los tests estáticos, que se definen de manera fija en el código, los tests dinámicos se generan y ejecutan de manera programática. Esto es útil cuando se necesita ejecutar una serie de tests que no se pueden definir de antemano, como pruebas basadas en datos externos o generados aleatoriamente.
Conceptos Clave
- DynamicTest: Representa un test dinámico en JUnit 5.
- DynamicContainer: Agrupa varios DynamicTest y otros DynamicContainer.
- DynamicTest.stream(): Método para crear un flujo de tests dinámicos.
Creando Tests Dinámicos
Para crear tests dinámicos, se utiliza la anotación @TestFactory en un método que retorna una colección de DynamicTest o DynamicContainer.
Ejemplo Básico
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.function.Executable;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class DynamicTestsExample {
@TestFactory
Collection<DynamicTest> dynamicTests() {
return Arrays.asList(
DynamicTest.dynamicTest("Test 1", () -> assertTrue(1 < 2)),
DynamicTest.dynamicTest("Test 2", () -> assertTrue(2 < 3))
);
}
}En este ejemplo, el método dynamicTests retorna una colección de DynamicTest. Cada DynamicTest se define con un nombre y un Executable que contiene el código del test.
Explicación del Código
- @TestFactory: Indica que el método es una fábrica de tests dinámicos.
- DynamicTest.dynamicTest: Método estático para crear un
DynamicTest. - Executable: Interfaz funcional que representa el código del test.
Usando DynamicContainer
Los DynamicContainer permiten agrupar varios DynamicTest y otros DynamicContainer, lo que es útil para organizar tests complejos.
Ejemplo con DynamicContainer
import org.junit.jupiter.api.DynamicContainer;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.util.Arrays;
import java.util.Collection;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class DynamicContainerExample {
@TestFactory
Collection<DynamicContainer> dynamicContainers() {
return Arrays.asList(
DynamicContainer.dynamicContainer("Container 1", Arrays.asList(
DynamicTest.dynamicTest("Test 1.1", () -> assertTrue(1 < 2)),
DynamicTest.dynamicTest("Test 1.2", () -> assertTrue(2 < 3))
)),
DynamicContainer.dynamicContainer("Container 2", Arrays.asList(
DynamicTest.dynamicTest("Test 2.1", () -> assertTrue(3 < 4)),
DynamicTest.dynamicTest("Test 2.2", () -> assertTrue(4 < 5))
))
);
}
}Explicación del Código
- DynamicContainer.dynamicContainer: Método estático para crear un
DynamicContainer. - Arrays.asList: Utilizado para crear una lista de
DynamicTestdentro de cadaDynamicContainer.
Ejercicio Práctico
Ejercicio
Crea un test dinámico que verifique si una lista de números es par o impar. La lista de números debe ser generada aleatoriamente.
Solución
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class DynamicTestExercise {
@TestFactory
Collection<DynamicTest> dynamicTests() {
List<Integer> numbers = generateRandomNumbers(10);
List<DynamicTest> dynamicTests = new ArrayList<>();
for (Integer number : numbers) {
dynamicTests.add(DynamicTest.dynamicTest("Test if " + number + " is even or odd", () -> {
if (number % 2 == 0) {
assertTrue(number % 2 == 0, number + " is even");
} else {
assertTrue(number % 2 != 0, number + " is odd");
}
}));
}
return dynamicTests;
}
private List<Integer> generateRandomNumbers(int count) {
List<Integer> numbers = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < count; i++) {
numbers.add(random.nextInt(100));
}
return numbers;
}
}Explicación del Código
- generateRandomNumbers: Método auxiliar para generar una lista de números aleatorios.
- dynamicTests.add: Añade un
DynamicTestpara cada número en la lista. - assertTrue: Verifica si el número es par o impar.
Conclusión
Los tests dinámicos en JUnit 5 proporcionan una manera flexible y poderosa de crear tests en tiempo de ejecución. Son especialmente útiles para escenarios donde los datos de prueba no se conocen de antemano o se generan dinámicamente. Con DynamicTest y DynamicContainer, puedes organizar y ejecutar tests de manera eficiente y estructurada.
En el siguiente módulo, exploraremos las mejores prácticas y consejos para escribir tests efectivos y organizar el código de tests.
Curso de JUnit
Módulo 1: Introducción a JUnit
Módulo 2: Anotaciones Básicas de JUnit
- Entendiendo @Test
- Usando @Before y @After
- Usando @BeforeClass y @AfterClass
- Ignorando Tests con @Ignore
Módulo 3: Aserciones en JUnit
Módulo 4: Tests Parametrizados
- Introducción a los Tests Parametrizados
- Creando Tests Parametrizados
- Usando @ParameterizedTest
- Tests Parametrizados Personalizados
Módulo 5: Suites de Tests
Módulo 6: Mocking con JUnit
Módulo 7: Características Avanzadas de JUnit
Módulo 8: Mejores Prácticas y Consejos
- Escribiendo Tests Efectivos
- Organizando el Código de Tests
- Desarrollo Guiado por Tests (TDD)
- Integración Continua con JUnit
