Pruebas parametrizadas con Theory e InlineData

Resumen

Reutilizar pruebas unitarias en xUnit te permite validar múltiples escenarios con una sola estructura usando los atributos Theory e InlineData. Aprenderás a parametrizar tus tests en C# para cubrir más casos sin duplicar código, algo clave si estás escribiendo pruebas en .NET.

¿Por qué parametrizar pruebas unitarias en xUnit?

Cuando escribes una prueba con el atributo Fact, estás validando un único escenario fijo. Si quieres comprobar varios casos, terminarías copiando la misma estructura una y otra vez. Y ahí es donde aparece el problema: código repetido, mantenimiento costoso y pruebas difíciles de leer.

La solución llega con Theory, un atributo que convierte tu método de prueba en una plantilla capaz de recibir parámetros. Cada conjunto de datos genera una ejecución independiente, así que el test runner te muestra cuál escenario pasó y cuál no.

¿Qué hace el atributo Theory en xUnit? Convierte un método de prueba en una plantilla parametrizable. A diferencia de Fact, permite ejecutar el mismo test con distintos valores de entrada y resultados esperados.

¿Cómo escribir una prueba con Theory e InlineData paso a paso?

Para este ejemplo se usa la función FromRomanToNumber, que recibe un número romano como string y devuelve su equivalente en int [02:00]. La estructura típica de un test parametrizado tiene tres elementos:

  • El atributo Theory reemplazando a Fact.
  • Uno o varios atributos InlineData con los valores de entrada y el resultado esperado.
  • Parámetros en el método que coinciden en orden y tipo con los datos del InlineData.

El método de prueba queda así en C#:

csharp [Theory] [InlineData("V", 5)] [InlineData("III", 3)] [InlineData("X", 10)] public void FromRomanToNumber(string romanNumber, int expected) { var result = strOperations.FromRomanToNumber(romanNumber); Assert.Equal(expected, result); }

Cada línea de InlineData representa un escenario distinto [04:30]. El primer valor llena el parámetro romanNumber y el segundo llena expected. El runner ejecuta la prueba tres veces, una por cada combinación.

¿Qué pasa si un escenario falla?

xUnit separa visualmente cada caso en el explorador de pruebas. Si agregas un dato incorrecto a propósito, por ejemplo [InlineData("P", -1)], ese escenario aparece como fallido mientras los demás siguen pasando [05:40]. Esa granularidad es una de las grandes ventajas frente a un Fact tradicional.

¿Cuál es la diferencia entre Fact y Theory? Fact define una prueba sin parámetros que valida un solo caso. Theory define una prueba parametrizada que se ejecuta varias veces, una por cada conjunto de datos suministrado con InlineData.

¿Cuándo conviene aplicar Theory en tus tests?

Usa Theory siempre que tengas una función con comportamiento uniforme pero múltiples entradas válidas. Algunos casos prácticos del proyecto:

  • Validar conversiones, como números romanos a enteros.
  • Probar funciones de transformación de texto, como QuantityInWords.
  • Unificar pruebas de booleanos, por ejemplo verificar si una palabra es palíndromo con casos true y false en un solo método [07:20].

Este último ejemplo es especialmente útil. En lugar de mantener dos métodos separados, uno para palíndromos válidos y otro para inválidos, los combinas en una sola prueba parametrizada y reduces a la mitad el código de testing.

¿Qué es InlineData en xUnit? Es un atributo que provee datos directamente en el código fuente para una prueba con Theory. Cada InlineData representa una ejecución independiente del test con sus propios valores de entrada y salida esperada.

La reutilización mediante parámetros forma parte de los principios de las pruebas unitarias bien diseñadas. Una prueba que escala con nuevos escenarios sin reescribir su lógica es una prueba mantenible.

¿En qué funciones de tu proyecto aplicarías Theory para reducir duplicación? Cuéntame en los comentarios cómo lo estructurarías.