¿Por qué las pruebas "verdes" no son aún una victoria?
\n\nImagine: escribió un centenar de pruebas unitarias, todas pasan con una marca verde, el pipeline de CI está feliz, el gerente está contento. Pero un mes después, una funcionalidad crítica falla en producción. ¿Le suena familiar? La mayoría de las veces, el problema es que probamos escenarios incorrectos o nos saltamos ramas enteras de código.
\n\nLa cobertura de código (code coverage) no es solo una métrica de moda para un informe. Es su linterna en la habitación oscura de la incertidumbre. Cuando empecé a trabajar con C#, pensaba que el 80% de cobertura era el ideal. Pero luego entendí: se puede tener un 100% de cobertura de líneas y aun así pasar por alto un error en la lógica de bifurcación. Por eso hoy analizaremos cómo medir correctamente la cobertura en C#, qué herramientas realmente ayudan y qué métricas vale la pena rastrear.
\n\n¿Qué es la cobertura de código y por qué es importante para un desarrollador de C#?
\n\nEn términos simples, la cobertura de código muestra qué porcentaje del código fuente de su aplicación se ejecutó durante la ejecución de las pruebas. Si escribió una prueba que llama al método CalculateDiscount(), pero no verifica la rama if (isPremiumUser), entonces esa rama permanece "sin cubrir".
Para un desarrollador de C#, la cobertura es un indicador de dos cosas:
\n- \n
- Confianza en la refactorización — ¿se puede cambiar el código sin miedo a romper algo? \n
- Integridad de las pruebas — ¿nos olvidamos de los casos límite? \n
Pero hay un matiz importante: la cobertura de código con pruebas en C# no garantiza la ausencia de errores. Solo indica que ciertas líneas fueron ejecutadas. Por eso no miramos solo el porcentaje, sino las métricas específicas.
\n\nMétricas principales de cobertura de código en .NET
\n\nCuando ejecuta un análisis de cobertura en C#, se encuentra con varios tipos de métricas. Analicemos cada una con un ejemplo de código real.
\n\nLine Coverage (cobertura de líneas)
\nLa métrica más simple. Cuenta cuántas líneas de código fueron alcanzadas por las pruebas. Ejemplo:
\n\npublic int Add(int a, int b)\n{\n if (a < 0) // línea 1\n return 0; // línea 2\n return a + b; // línea 3\n}\n\nSi su prueba llama a Add(5, 3), se ejecutarán las líneas 1 y 3. La línea 2 permanecerá sin cubrir. Line coverage mostrará un 66% (2 de 3 líneas).
Branch Coverage (cobertura de bifurcaciones)
\nUna métrica más honesta. Considera todas las rutas de ejecución posibles. En nuestro ejemplo, hay dos rutas: cuando a < 0 y cuando no. Si solo probó el caso con un número positivo, Branch coverage será del 50%.
Precisamente Branch coverage a menudo revela "agujeros" en las pruebas. Recomiendo aspirar a un 80%+ específicamente en esta métrica.
\n\nCyclomatic Complexity y su relación con la cobertura
\nAunque no es una métrica de cobertura directa, la complejidad ciclomática muestra cuántas pruebas se necesitan escribir para una cobertura completa. Cuanto mayor sea la complejidad del método, más pruebas se requieren. Si ve un método con una complejidad ciclomática de 15 y una cobertura del 90%, probablemente no esté probando todos los escenarios.
\n\nHerramientas para medir la cobertura de código en C#
\n\nEn el ecosistema .NET hay varias herramientas potentes. Hablaré de las tres más populares con las que he trabajado personalmente.
\n\nCoverlet — gratuito e integrado en .NET
\nSi usa .NET 6+, Coverlet ya está disponible a través de NuGet. Es mi herramienta favorita para CI/CD porque no requiere instalar programas adicionales.
\n\nInstalación:
\ndotnet add package coverlet.msbuild\ndotnet add package coverlet.collector\n\nEjecución con informe:
\ndotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover\n\nObtendrá un archivo coverage.opencover.xml que puede visualizar con ReportGenerator:
dotnet tool install -g dotnet-reportgenerator-globaltool\nreportgenerat