Pruebas basadas en propiedades en C++: atrapa errores que no buscabas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Qué pasa si tus pruebas unitarias mienten?

\n

Escribiste cien pruebas unitarias. Pasan. El código en C++ se ve perfecto. Pero cuando ejecutas la aplicación en producción, falla con un segmentation fault en la petición número 100500. ¿Dolor familiar?

\n

Las pruebas unitarias tradicionales solo verifican lo que tú mismo inventaste. Son ciegas a escenarios que no se te ocurrieron. Las pruebas basadas en propiedades (o property-based testing, PBT) resuelven este problema radicalmente: no verifican ejemplos concretos, sino que demuestran propiedades (properties) de tu código para millones de datos de entrada aleatorios.

\n

En este artículo, analizaremos cómo implementar pruebas basadas en propiedades en C++ con la librería RapidCheck, y veremos cómo atrapa errores que las pruebas unitarias comunes pasan por alto. ¿Listo para hacer sufrir a tu código de verdad? ¡Vamos allá!

\n\n

Pruebas basadas en propiedades: filosofía en 30 segundos

\n

Imagina que estás probando una función de ordenamiento. Prueba típica: sort([3,1,2]) == [1,2,3]. Bien, verificaste un caso.

\n

Enfoque basado en propiedades: «Para cualquier lista de números enteros, después de ordenar la longitud no cambia, los elementos están en orden ascendente, y cada elemento de la lista original está presente en la lista ordenada». El framework genera cientos de listas aleatorias (incluyendo vacías, con duplicados, con números negativos) y verifica estas propiedades.

\n

Idea clave: describes invariantes (properties) que deben cumplirse siempre, no entradas y salidas específicas.

\n\n

¿Cuándo es especialmente útil PBT en C++?

\n
    \n
  • Algoritmos y estructuras de datos (ordenamientos, búsqueda, grafos)
  • \n
  • Analizadores sintácticos y serializadores (codificación/decodificación)
  • \n
  • Funciones matemáticas (operaciones inversas, rangos de valores)
  • \n
  • Manejo de memoria (fugas, doble liberación)
  • \n
  • Cualquier código donde haya invariantes claros
  • \n
\n\n

RapidCheck: tu nuevo mejor amigo

\n

En C++ hay varias librerías para PBT, pero RapidCheck es la más madura y cómoda. Está inspirada en la librería QuickCheck de Haskell y se integra perfectamente con Google Test y Catch2.

\n

La instalación es simple: es una librería header-only, basta con copiar los archivos de include/rapidcheck a tu proyecto. O usa Conan/vcpkg.

\n\n

Primera prueba: propiedad de operación inversa

\n

Supongamos que tenemos una función que codifica una cadena en base64 y la decodifica de vuelta. ¿Qué propiedad es obvia? «Decodificar después de codificar devuelve la cadena original».

\n
#include <rapidcheck.h>\n#include <string>\n\nstd::string encode_base64(const std::string& input);\nstd::string decode_base64(const std::string& input);\n\nint main() {\n    rc::check("Decodificar después de codificar devuelve el original",\n              [](const std::string& original) {\n                  // El generador de cadenas ya está incorporado\n                  auto encoded = encode_base64(original);\n                  auto decoded = decode_base64(encoded);\n                  RC_ASSERT(decoded == original);\n              });\n    return 0;\n}\n
\n

¿Qué sucede aquí? RapidCheck genera cadenas aleatorias (incluyendo vacías, con Unicode, con bytes nulos). Para cada una, verifica la propiedad. Si encuentra un contraejemplo — mínimo (shrinking), que aún rompe la prueba. Esto es oro: no obtienes solo «hay un error», sino un caso concreto y reproducible.

\n\n

Propiedades avanzadas: más que igualdad

\n

Monotonía e idempotencia

\n

Para la función remove_duplicates:

\n
    \n
  • Idempotencia: si se aplica dos veces, el resultado no cambia.
  • \n
  • El orden no importa: la lista resultante contiene los mismos elementos que la original, pero sin duplicados.
  • \n
\n
#include <vector>\n#include <algo                

Blogs

Book Recommendations