PHPUnit es una de las herramientas más populares para realizar pruebas unitarias en proyectos PHP. Uno de los métodos más eficientes para escribir pruebas reutilizables es el uso de @dataProvider
, una característica de PHPUnit que permite alimentar a los métodos de prueba con diferentes conjuntos de datos.
En este artículo, exploraremos en detalle cómo utilizar @dataProvider
en PHPUnit, sus ventajas y cómo implementarlo de manera efectiva para escribir pruebas más eficientes y flexibles.
En PHPUnit, un *Data Provider* es un método que devuelve un conjunto de datos que se utilizarán como entradas para las pruebas. Este método se asocia con una prueba específica a través de la anotación @dataProvider
. Cada conjunto de datos se pasa a la prueba en una ejecución separada, lo que permite que un solo método de prueba se ejecute varias veces con diferentes datos.
Esto es particularmente útil cuando tienes un escenario de prueba que debe verificarse con múltiples variaciones de entrada, como diferentes valores o combinaciones de parámetros.
El uso de @dataProvider
tiene varias ventajas:
1. Código de prueba más limpio: Al evitar la duplicación de pruebas con entradas similares, el código se vuelve más fácil de mantener.
2. Facilidad de mantenimiento: Si los escenarios de prueba cambian, solo necesitas modificar los datos en un lugar.
3. Flexibilidad: Puedes ejecutar múltiples casos de prueba en un solo método, cada uno con datos diferentes.
Veamos un ejemplo simple para entender cómo funciona @dataProvider
en PHPUnit. Supongamos que estamos probando una función que suma dos números.
El primer paso es definir un método de prueba que acepte parámetros. En este ejemplo, la función que vamos a probar se llama sumar()
y toma dos números como entrada.
class CalculadoraTest extends \PHPUnit\Framework\TestCase
{
/**
* @dataProvider proveedorDeSumas
*/
public function testSumar($a, $b, $resultadoEsperado)
{
$calculadora = new Calculadora();
$this->assertEquals($resultadoEsperado, $calculadora->sumar($a, $b));
}
}
El siguiente paso es crear un método que provea los datos. Este método debe devolver un array de arrays, donde cada sub-array contiene los parámetros que serán pasados al método de prueba.
class CalculadoraTest extends \PHPUnit\Framework\TestCase
{
public function proveedorDeSumas()
{
return [
[1, 1, 2],
[2, 2, 4],
[5, 5, 10],
[-1, 1, 0],
[0, 0, 0],
];
}
/**
* @dataProvider proveedorDeSumas
*/
public function testSumar($a, $b, $resultadoEsperado)
{
$calculadora = new Calculadora();
$this->assertEquals($resultadoEsperado, $calculadora->sumar($a, $b));
}
}
En este ejemplo, el método proveedorDeSumas()
proporciona cinco conjuntos de datos. La prueba testSumar()
se ejecutará cinco veces, cada vez utilizando un conjunto diferente de datos (los valores $a
, $b
y $resultadoEsperado
).
Para completar el ejemplo, necesitamos la clase Calculadora
con el método sumar()
que realiza la suma de dos números.
class Calculadora
{
public function sumar($a, $b)
{
return $a + $b;
}
}
Al ejecutar las pruebas, PHPUnit ejecutará el método testSumar()
cinco veces, una vez para cada conjunto de datos que proporciona el método proveedorDeSumas()
.
PHPUnit 9.5.0 by Sebastian Bergmann and contributors.
..... 5 / 5 (100%)
Time: 00:00.012, Memory: 4.00 MB
OK (5 tests, 5 assertions)
El ejemplo anterior es muy básico. Sin embargo, puedes aprovechar @dataProvider
de maneras más avanzadas para manejar casos más complejos.
Puedes probar tu código con diferentes tipos de datos (enteros, cadenas, booleanos, etc.) para asegurarte de que funcione en una variedad de situaciones.
public function proveedorDeDatosMixtos()
{
return [
[1, "1", 2], // Suma de un entero y una cadena
[true, 1, 2], // Suma de un booleano y un entero
[null, 0, 0], // Suma de null y un entero
];
}
Un solo Data Provider
puede ser utilizado por múltiples métodos de prueba. Esto es útil si varios métodos de prueba requieren conjuntos de datos similares.
public function testMultiplicar($a, $b, $resultadoEsperado)
{
$calculadora = new Calculadora();
$this->assertEquals($resultadoEsperado, $calculadora->multiplicar($a, $b));
}
/**
* @dataProvider proveedorDeSumas
*/
public function testSumar($a, $b, $resultadoEsperado)
{
$calculadora = new Calculadora();
$this->assertEquals($resultadoEsperado, $calculadora->sumar($a, $b));
}
En este caso, tanto testSumar()
como testMultiplicar()
podrían compartir el mismo @dataProvider
.
Es posible que desees utilizar métodos estáticos para los Data Providers
, especialmente si el método no necesita acceder a ninguna propiedad de la clase.
public static function proveedorEstatico()
{
return [
[1, 1, 2],
[2, 2, 4],
[3, 3, 6],
];
}
Recuerda que, si usas un método estático como Data Provider, la anotación @dataProvider
debe referirse al método de la misma manera:
/**
* @dataProvider proveedorEstatico
*/
public function testSumar($a, $b, $resultadoEsperado)
{
$calculadora = new Calculadora();
$this->assertEquals($resultadoEsperado, $calculadora->sumar($a, $b));
}
Puedes utilizar @dataProvider
para probar también situaciones en las que se espera que tu código arroje excepciones. Veamos un ejemplo donde el método sumar()
debería lanzar una excepción si se intenta sumar un valor no numérico.
public function proveedorDeExcepciones()
{
return [
[1, 'a'], // Una cadena no numérica
[null, 2], // null como parámetro
[[], 3], // Un array como parámetro
];
}
/**
* @dataProvider proveedorDeExcepciones
*/
public function testSumaConExcepciones($a, $b)
{
$this->expectException(\InvalidArgumentException::class);
$calculadora = new Calculadora();
$calculadora->sumar($a, $b);
}
En este ejemplo, el Data Provider proveedorDeExcepciones()
entrega casos en los que el método sumar()
debe arrojar una excepción debido a parámetros inválidos.
El uso de @dataProvider
en PHPUnit es una práctica recomendada para crear pruebas más eficientes y fáciles de mantener. Al aprovechar esta funcionalidad, puedes probar tu código con múltiples conjuntos de datos sin duplicar código, lo que resulta en pruebas más limpias y robustas.
Ya sea que estés probando simples operaciones matemáticas, validando entradas mixtas o verificando que se manejen correctamente las excepciones, @dataProvider
te proporciona la flexibilidad que necesitas para mejorar la cobertura y calidad de tus pruebas. ¡Implementa Data Providers en tu próximo proyecto y observa cómo mejora tu flujo de trabajo de pruebas! 🤙
Jorge García
Fullstack developer