Tests unitarios y code coverage en Go
Clase 17 de 30 • Curso de Go Intermedio: Programación Orientada a Objetos y Concurrencia
Contenido del curso
Programación orientada a objetos
- 5

Programación Orientada a Objetos en Go: Análisis y Comparativa
06:51 min - 6

Equivalente de Clases en Go: Uso de Structs y Propiedades
06:41 min - 7

Métodos en Structs: Implementación de Receiver Functions en Go
08:54 min - 8

Implementación de Constructores en Go: Ejemplos y Mejores Prácticas
10:48 min - 9

Herencia y Composición en Programación Orientada a Objetos
14:50 min - 10

Interfaces y Polimorfismo en TypeScript y Go
12:35 min - 11

Patrón Abstract Factory: Interfaces y Polimorfismo en Go
07:37 min - 12

Implementación del Patrón Factory en Go para Notificaciones
10:10 min - 13

Funciones Anónimas en Go: Uso y Consideraciones Prácticas
06:56 min - 14

Funciones Variádicas y Retornos con Nombre en Go
10:51 min
Go Modules
Testing
- 17

Tests unitarios y code coverage en Go
Viendo ahora - 18

Cobertura de Código y Testing en Go: Mejorando la Calidad del Software
09:56 min - 19

Profiling de Código en Go para Optimización de Rendimiento
08:46 min - 20

Testing Unitario en Go: Uso de Mock Services
11:51 min - 21

Testeo Unitario de Funciones con MOOC en Go
08:53 min
Concurrencia
- 22

Canales con y sin buffer en Go: diferencias y uso práctico
06:23 min - 23

Sincronización de Rutinas en Go con Wait Group
07:26 min - 24

"Uso de Canales con Buffer como Semáforos en Go"
09:00 min - 25

Manejo de Canales de Lectura y Escritura en Go
09:34 min - 26

Concurrencia en Go: Creación de Worker Pools y Fibonacci
11:23 min - 27

Multiplexación de Canales en Go con Select y Case
07:13 min
Proyecto: servidor con worker pools
Conclusión
¿Qué es el testing y por qué es importante?
El testing es una parte fundamental en el ciclo de desarrollo de software. Aunque es un tema vasto que podría requerir cursos enteros dedicados, en este contexto nos centraremos en crear pruebas unitarias para el código que desarrollamos. Las pruebas unitarias son pequeñas evaluaciones que verifican el comportamiento de funciones individuales. Este proceso no solo valida que el código funciona como se espera, sino que también nos ayuda a garantizar la calidad y a detectar errores con anticipación. Además, vamos a medir el code coverage, que nos indica qué porcentaje de nuestro código está cubierto por estas pruebas.
¿Cómo creamos pruebas unitarias en Go?
Para ilustrar el proceso de creación de pruebas unitarias en Go, comenzamos creando un archivo principal, main.go, que contiene una función simple de suma. Después, crearemos un archivo de pruebas, main_test.go, donde escribiremos las pruebas para la función de suma. Este archivo de pruebas debe seguir un formato específico para que Go lo reconozca, usando el sufijo _test.go.
Configuración inicial
Primero, definimos el paquete principal y la función que vamos a probar:
package main
func sum(x, y int) int {
return x + y
}
Creación de la prueba unitaria
En el archivo main_test.go, definimos el paquete y la función de prueba. Es esencial importar el paquete testing, ya que proporciona las herramientas necesarias para verificar los resultados de las pruebas.
package main
import "testing"
func TestSum(t *testing.T) {
total := sum(5, 5)
if total != 10 {
t.Errorf("Suma incorrecta, obtuvimos %d, pero esperábamos %d", total, 10)
}
}
Ejecutando las pruebas
Para ejecutar las pruebas, utilizamos el comando go test desde la terminal. Si configuramos correctamente nuestro módulo con go mod init, las pruebas deberían ejecutarse sin problemas. En caso de haber errores, Go reportará los fallos y sus ubicaciones específicas en el código.
¿Cómo utilizamos tablas de prueba para múltiples casos?
Un patrón común para aplicar pruebas en Go es el uso de tablas de prueba. Esta técnica nos permite definir múltiples escenarios de prueba en un slice de structs, facilitando la iteración y ejecución de cada caso.
Creación de una tabla de pruebas
Definimos una estructura para nuestros casos de prueba, que incluya los valores de entrada y el resultado esperado.
func TestSum(t *testing.T) {
testCases := []struct{a, b, expected int}{
{1, 2, 3},
{2, 2, 4},
{25, 26, 51},
}
for _, tc := range testCases {
result := sum(tc.a, tc.b)
if result != tc.expected {
t.Errorf("Suma incorrecta, obtuvimos %d, pero esperábamos %d", result, tc.expected)
}
}
}
Ventajas de las tablas de pruebas
Este enfoque no solo organiza el proceso de pruebas, sino que también permite agregar y modificar casos fácilmente sin cambiar la lógica de prueba. Además, proporciona un marco claro para identificar fallos específicos cuando ocurren.
¿Qué impacto tiene el code coverage?
El code coverage es una métrica que indica qué parte de nuestro código ha sido ejecutada durante las pruebas. Aunque Go no obliga a cubrir el 100% del código, un bajo porcentaje de cobertura podría ocultar errores en partes no probadas. Go ofrece comandos para generar informes de cobertura, permitiéndonos identificar y mejorar áreas deficientes en nuestras pruebas.
Integración del code coverage
Para calcular el code coverage, podemos usar el comando go test -cover, que mostrará un resumen del porcentaje de código cubierto por las pruebas. Esta práctica nos ayuda a mantener un estándar de calidad alto y a asegurar que todas las partes críticas del código estén debidamente verificadas.
El uso consciente de pruebas unitarias y el seguimiento del code coverage no solo mejoran la calidad del software, sino que también aumentan la confianza en nuestras aplicaciones. Invito a continuar explorando y aplicando estos conceptos en sus proyectos para asegurar un desarrollo más sólido y eficiente.