Cómo medir la cobertura de pruebas en Go y no volverse loco
\n\nHas escrito pruebas para tu aplicación Go. ¿Te sientes como un superhéroe? Bien hecho. Pero hay un detalle: ¿cuánto código exactamente está cubierto por las pruebas? Sin respuesta a esta pregunta, tu confianza es solo una adivinanza.
\n\nLa pregunta "How to measure test coverage in Go" es una de las más populares en Stack Overflow (decenas de miles de visitas). Y no es casualidad. Los desarrolladores no solo quieren escribir pruebas, sino entender qué tan efectivas son. En este tutorial, analizaremos todas las formas de medir la cobertura de pruebas en Go: desde comandos básicos hasta técnicas avanzadas con perfiles e informes HTML.
\n\n¿Qué es la cobertura de pruebas y por qué medirla?
\n\nTest coverage (cobertura de código por pruebas) es una métrica que muestra qué porcentaje de tu código fuente se ejecuta durante las pruebas. Se expresa en porcentajes. El 100% de cobertura no siempre es el Santo Grial, pero vale la pena aspirar a valores altos.
\n\n¿Por qué es necesario?
\n- \n
- Control de calidad: ves qué partes del código quedaron sin pruebas \n
- Confianza en la refactorización: una alta cobertura reduce el riesgo de romper algo \n
- Métricas de CI/CD: se puede configurar un umbral de cobertura y no permitir código con baja cobertura \n
- Documentación: las pruebas son documentación viva, y la cobertura muestra qué tan completa es \n
La trampa: cobertura ≠ calidad de las pruebas
\nRecuerda: 100% de cobertura no garantiza la ausencia de errores. Se pueden escribir pruebas que simplemente llamen a funciones pero no verifiquen nada. La cobertura es una métrica cuantitativa. La calidad de las pruebas es cualitativa. Usa ambos enfoques.
\n\nMedición básica: go test -cover
\n\nEmpecemos con lo más simple. Go tiene soporte integrado para cobertura directamente en la herramienta go test. Creemos un proyecto simple y veamos cómo funciona.
Crea el archivo math.go:
package main\n\nfunc Add(a, b int) int {\n return a + b\n}\n\nfunc Subtract(a, b int) int {\n return a - b\n}\n\nfunc Multiply(a, b int) int {\n return a * b\n}\n\nfunc Divide(a, b int) (int, error) {\n if b == 0 {\n return 0, nil // Error: debería ser return 0, errors.New("division by zero")\n }\n return a / b, nil\n}\n\nY ahora, la prueba (math_test.go):
package main\n\nimport "testing"\n\nfunc TestAdd(t *testing.T) {\n result := Add(2, 3)\n if result != 5 {\n t.Errorf("expected 5, got %d", result)\n }\n}\n\nfunc TestSubtract(t *testing.T) {\n result := Subtract(10, 4)\n if result != 6 {\n t.Errorf("expected 6, got %d", result)\n }\n}\n\n// Intencionalmente no probamos Multiply y Divide\n\nAhora ejecutemos las pruebas con la bandera -cover:
go test -cover\n\nLa salida será algo así:
\n\nok example/math 0.002s coverage: 50.0% of statements\n\nCorrecto: está cubierto el 50% del código, porque Multiply y Divide no se prueban. Pero esto es solo un número general. ¿Y si queremos ver un perfil detallado de cobertura?
Perfil de cobertura: go test -coverprofile
\n\nLa bandera -coverprofile guarda información detallada sobre la cobertura en un archivo:
go test -coverprofile=coverage.out\n\nAhora apareció un archivo coverage.out en la carpeta. Ábrelo: es un formato de texto donde cada línea muestra si se ejecutó una instrucción de código específica. Pero leerlo manualmente es aburrido. Pasemos a la visualización.
Informe HTML: go tool cover -html
\n\nLa forma más conveniente de analizar la cobertura es un informe HTML. Resalta el código ejecutado en verde y el no ejecutado en rojo.
\n\ngo tool cove