Tu prueba unitaria miente (y lo sabes)
\n\nImagina: escribiste 50 pruebas unitarias, todas verdes, cobertura del 90%. Estás contento. Pero una semana después, el sistema en producción falla. Resulta que tu método SortArray() funciona perfectamente para [1, 2, 3] y [3, 1, 2], pero falla con [int.MaxValue, -1, 0]. ¿Te suena?
El problema de las pruebas unitarias clásicas es el sesgo del desarrollador. Escribes pruebas para los datos que esperas. Los hackers, los usuarios reales y las condiciones límite aleatorias siguen otras reglas.
\n\nAquí entra en escena el pruebas basadas en propiedades en C# (o testing basado en propiedades). En lugar de verificar "si A, entonces B", describes propiedades que siempre deben ser verdaderas. Y el framework genera cientos de datos de entrada aleatorios y verifica tus afirmaciones.
\n\nEn este artículo, analizaremos cómo implementar pruebas basadas en propiedades en C# con la librería FsCheck, escribiremos ejemplos reales y veremos cómo atrapa errores que las pruebas comunes pasan por alto.
\n\n¿Qué son las pruebas basadas en propiedades?
\n\nLas pruebas basadas en propiedades son un enfoque en el que formulas invariantes (propiedades) de tu programa. Por ejemplo:
\n- \n
- "Después de ordenar, la longitud del array no cambia" \n
- "El orden inverso de una cadena da la cadena original" \n
- "La suma de dos números positivos siempre es positiva" \n
El framework (por ejemplo, FsCheck) genera decenas y cientos de datos de entrada aleatorios y verifica que la propiedad se cumpla para todos. Si se encuentra un contraejemplo, la prueba falla y obtienes los valores específicos que rompieron el código.
\n\nA diferencia de las pruebas unitarias, no escribes Assert.AreEqual(3, Add(1,2)). Escribes Assert(x + y == y + x) — y pruebas la conmutatividad para miles de pares de números.
Diferencia con las pruebas unitarias comunes
\n\n| Pruebas unitarias | Pruebas basadas en propiedades |
|---|---|
| Verifican ejemplos concretos | Verifican leyes generales |
| Los datos los define el desarrollador | Los datos los genera el framework |
| Pasan por alto casos límite | Exploran automáticamente los límites |
| Fáciles de leer | Requieren pensamiento abstracto |
Librería FsCheck: tu herramienta principal
\n\nEn el mundo de C#, el estándar de facto para pruebas basadas en propiedades es FsCheck (originalmente un puerto de la librería QuickCheck de Haskell). Se integra con xUnit, NUnit y MSTest.
\n\nLa instalación es sencilla:
\ndotnet add package FsCheck\ndotnet add package FsCheck.Xunit // para integración con xUnit\n\nFsCheck puede generar datos aleatorios para tipos primitivos (int, string, float), listas, arrays, tuplas e incluso tipos personalizados (a través de generadores personalizados).
Escribimos nuestra primera prueba basada en propiedades en C#
\n\nEmpecemos con algo simple: verificar que la operación de suma de números enteros es conmutativa.
\n\nusing FsCheck;\nusing FsCheck.Xunit;\n\npublic class AdditionTests\n{\n [Property]\n public bool Commutative_Addition(int x, int y)\n {\n return x + y == y + x;\n }\n}\n\nEjecuta la prueba. FsCheck generará 100 pares aleatorios de int (por defecto) y verificará la propiedad. Si no se encuentra ningún contraejemplo, la prueba es verde. Si nos hubiéramos equivocado (por ejemplo, escribiendo x - y == y - x), la prueba fallaría con un ejemplo concreto: (5, 3) — porque 5 - 3 != 3 - 5.
Analizando el código
\n- \n
- [Property] — atributo que le indica a FsCheck que esta es una prueba basada en propiedades. \n
- El método devuelve
bool— si devuelvefalse, la prueba falla. \n - Los parámetros
int x, int y— FsCheck los sustituirá automáticamente con valores aleatorios.