¿Por qué la cobertura de código no es solo una marca en CI/CD?
\n\nImagina: escribiste en Rust un módulo para analizar archivos de configuración complejos. El compilador está feliz, las pruebas pasan, pero un mes después la producción falla con un error en un caso límite poco común. ¿Te suena familiar? Aquí es donde entra en escena la cobertura de código en Rust — una métrica que muestra qué porcentaje de tu código se ejecuta realmente durante las pruebas.
\n\nPero seamos honestos: perseguir el 100% de cobertura es una trampa. Es mucho más importante entender qué líneas quedaron sin probar y por qué. En este artículo analizaremos las tres herramientas principales para Rust: tarpaulin, grcov y el conjunto de herramientas LLVM integrado. Aprenderás cómo convertir porcentajes fríos en información procesable para la refactorización.
¿Por qué un desarrollador de Rust debería monitorear la cobertura?
\nRust es conocido por su seguridad de memoria, pero eso no elimina los errores lógicos. La cobertura de código ayuda a:
\n- \n
- Detectar "código muerto" — funciones o ramas que nunca se llaman. \n
- Aumentar la confianza al refactorizar — sabiendo que las rutas críticas están cubiertas por pruebas. \n
- Mejorar la documentación — las pruebas a menudo sirven como la mejor documentación si cubren todos los escenarios. \n
La métrica principal es line coverage (cobertura de líneas), pero también veremos branch coverage (cobertura de ramificaciones), que en Rust es especialmente importante debido a la abundancia de expresiones match.
\n\nHerramienta n.º 1: cargo-tarpaulin — simplicidad y velocidad
\ntarpaulin es la herramienta más popular para la cobertura de código en Rust. Funciona "de fábrica" y no requiere configuración compleja. Instalación:
cargo install cargo-tarpaulin\nEjecución del análisis básico:
\ncargo tarpaulin --out Html\nEste comando generará un informe HTML en la carpeta tarpaulin-report.html. Lo abrimos y vemos un mapa de colores de tu proyecto: líneas verdes (cubiertas por pruebas), rojas (no cubiertas) y grises (no ejecutables, por ejemplo, comentarios).
Ejemplo: probando una función simple
\nCreemos un archivo src/lib.rs con una función para calcular el factorial:
pub fn factorial(n: u32) -> u32 {\n match n {\n 0 | 1 => 1,\n _ => n * factorial(n - 1),\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n\n #[test]\n fn test_factorial() {\n assert_eq!(factorial(0), 1);\n assert_eq!(factorial(1), 1);\n assert_eq!(factorial(5), 120);\n }\n}\nEjecutamos tarpaulin:
\ncargo tarpaulin --ignore-tests --out Html\nLa bandera --ignore-tests excluye el código de prueba del informe. Resultado: 100% de cobertura para esta función. Pero compliquemos la tarea: agreguemos manejo de errores:
pub fn factorial_safe(n: i32) -> Result<u32, String> {\n if n < 0 {\n return Err("¡Número negativo!".to_string());\n }\n Ok(factorial(n as u32))\n}\nAhora tarpaulin mostrará que la rama Err no está cubierta por pruebas. Agreguemos una prueba:
#[test]\nfn test_negative() {\n assert!(factorial_safe(-5).is_err());\n}\nDespués de ejecutar nuevamente, la cobertura vuelve al 100%.
\n\nConfiguración avanzada de tarpaulin
\nPara proyectos grandes, usa:
\n- \n
--fail-under 80— salida con error si la cobertura es inferior al 80%. \n --skip-clean— no recompilar el proyecto si los cambios son menores. \n --engine llvm— usar el conjunto de herramientas LLVM (experimental, pero más preciso). \n
Herramienta n.º 2: grcov — el rey de las integraciones
\ngrcov es una herramienta más flexible que funciona con el conjunto de herramientas LLVM. Es especialmente útil si usas CI/CD (GitHub Actions, GitLab