Introducción: ¿Por qué las pruebas "verdes" no son aún una victoria?
\n\nImagine: ejecuta mil unit-tests, todos pasan con una marca verde, el pipeline de CI está feliz, el jefe está contento. Pero pasa una semana y un error crítico aparece en producción. ¿Le suena familiar? La mayoría de las veces el problema es que las pruebas existen, pero no verifican el código que realmente se ejecuta. Pueden estar probando solo el 10% del código fuente, mientras que el 90% restante es una "zona gris" donde se esconden los errores.
\n\nAquí es donde entra en escena la cobertura de código con pruebas en C++ (code coverage). No es solo una métrica de moda para reportar al cliente. Es su máquina de rayos X que muestra: qué líneas de código se ejecutan realmente durante las pruebas y cuáles nunca se han ejecutado. Hoy analizaremos cómo configurar correctamente las herramientas de cobertura en C++, qué métricas son realmente importantes y cómo no ahogarse en falsos positivos.
\n\n¿Qué es la cobertura de código y por qué la necesita un desarrollador de C++?
\n\nLa cobertura de código (code coverage) es una métrica que muestra qué porcentaje del código fuente de su programa se ejecutó durante la ejecución de las pruebas. En C++ esto es especialmente crítico, porque el lenguaje permite escribir código de bajo nivel, optimizaciones y magia de plantillas que puede "disparar" en el momento más inesperado.
\n\nPrincipales tipos de métricas de cobertura
\nNo todas las métricas son igualmente útiles. Esto es lo que realmente importa:
\n- \n
- Line Coverage (cobertura de líneas) — la métrica más básica. Cuántas líneas del código fuente fueron afectadas. Fácil de medir, pero fácil de engañar. \n
- Branch Coverage (cobertura de ramificaciones) — verifica si se recorrieron ambas ramas de cada
if/elseoswitch. Mucho más honesto que el line coverage. \n - Function Coverage (cobertura de funciones) — si la función fue llamada al menos una vez. Útil para encontrar código "muerto". \n
- Condition Coverage (cobertura de condiciones) — verifica todas las subexpresiones en operadores lógicos complejos (
&&,||). El más estricto, pero también el que más recursos consume. \n
Para un proyecto típico de C++, se considera una buena práctica un objetivo del 70-80% de line coverage y al menos un 60% de branch coverage. El 100% de cobertura es una utopía, pero aspirar al 90% en módulos críticos (gestión de memoria, protocolos de red) es una tarea perfectamente realista.
\n\nHerramientas para el análisis de cobertura de código C++
\n\nEl ecosistema de C++ ofrece varias herramientas potentes. Veremos las 3 principales que se utilizan realmente en producción.
\n\n1. Gcov — el clásico de GCC
\ngcov es una herramienta integrada en el compilador GCC. Funciona a nivel de código máquina, por lo que da resultados muy precisos. Principales ventajas: gratuito, abierto, funciona con CMake y Makefile.
Cómo ejecutarlo:
\n// Compilamos con banderas de cobertura\ng++ -fprofile-arcs -ftest-coverage -O0 main.cpp -o test_app\n\n// Ejecutamos las pruebas\n./test_app\n\n// Generamos el informe\ngcov main.cpp\nDespués de esto, obtendrá archivos *.gcov donde se mostrará cuántas veces se ejecutó cada línea. Desventaja: el formato de salida es texto, no muy visual.
2. LCOV — interfaz gráfica para Gcov
\nlcov es una capa sobre gcov que genera informes HTML atractivos. Podrá ver líneas verdes (cubiertas) y rojas (no cubiertas) directamente en el navegador.
# Recopilamos datos de cobertura\nlcov --capture --directory . --output-file coverage.info\n\n# Generamos HTML\ngenhtml coverage.info --output-directory coverage_report\nEste es el estándar de la industria para CI/CD. Jenkins, GitLab CI, GitHub Actions — en todos se puede configurar la generación automática de LCOV.
\n\n3. Clang Sanitizer Coverage (basado en código fuente)
\nSi usa Clang, tiene acceso a -fsanitize-coverage. E