Cultura de Pruebas en Go: Simple, Rápida, Basada en Tablas
Go trata las pruebas como código ordinario en el mismo módulo, compilado por la misma toolchain y ejecutado con un solo comando.
Busca en todas las páginas de la documentación
Go trata las pruebas como código ordinario en el mismo módulo, compilado por la misma toolchain y ejecutado con un solo comando.
Ese diseño impulsa a los equipos hacia pruebas pequeñas, rápidas y legibles en lugar de harnesses pesados.
testing incorporado de Go más go test es la capa de calidad predeterminada: sin bosques XML al estilo JUnit, sin bibliotecas de aserción obligatorias y sin un proceso de ejecución de pruebas separado para configurar.TestXxx, BenchmarkXxx, ExampleXxx, FuzzXxx, pruebas basadas en tablas, subpruebas t.Run, -race, perfiles de cobertura.Go proporciona un único vocabulario de pruebas en la biblioteca estándar.
Nombra las funciones TestSomething(t *testing.T), colócalas en something_test.go junto a something.go y ejecuta go test.
El compilador construye un binario de prueba que enlaza tu paquete más los archivos de prueba; go test lo ejecuta e informa de éxito/fallo.
No se requiere un archivo de configuración global para la mayoría de los paquetes.
Simple significa que los lectores ven el flujo organizar-actuar-afirmar en Go plano.
Una aserción fallida suele ser if got != want { t.Fatalf(...) } o una ayuda delgada, no un DSL con veinte matchers.
Rápido es una expectativa cultural respaldada por herramientas.
go test almacena en caché los resultados exitosos de los paquetes indexados por entradas; los paquetes sin cambios omiten la reejecución.
Los equipos apuntan a pruebas de paquete de menos de un segundo para que go test ./... se ejecute en cada commit.
Basado en tablas es la forma idiomática de agregar casos sin copiar y pegar funciones de prueba.
Una slice de structs contiene name, entradas y salidas esperadas; un bucle llama a t.Run por cada fila.
La tabla es la especificación; el bucle es el harness.
production.go *_test.go
| |
+-------- mismo paquete -+
|
go test ./...
|
éxito / fallo por paquete
Modos de paquete: go test puede ejecutar pruebas en el paquete bajo prueba (package foo) o como un paquete de prueba externo (package foo_test) para ejercitar solo las APIs exportadas.
Ambos compilan con el mismo comando; la elección señala la intención a los consumidores.
Subpruebas (t.Run) dan nombres jerárquicos en la salida y permiten la ejecución paralela con t.Parallel() dentro de un bucle de tabla.
Los fallos identifican el nombre del caso (TestParse/empty_input) en lugar de un número de línea en una prueba monolítica.
Ejemplos son pruebas que también aparecen en la documentación.
El comentario // Output: de una función Example es verificado por go test, manteniendo honesto a godoc.
Benchmarks miden ns/op y asignaciones; pruebas de fuzzing mutan las entradas para encontrar fallos.
Los tres usan el mismo nombramiento de archivos y el punto de entrada go test con diferentes firmas de función.
Detector de carreras (go test -race) instrumenta el acceso a la memoria para detectar carreras de datos que pasan bajo la programación normal.
Es más lento y pertenece a CI o pre-push, no a cada guardado.
func TestAdd(t *testing.T) {
tests := []struct{ a, b, want int }{{1, 2, 3}}
for _, tc := range tests {
t.Run("", func(t *testing.T) {
if got := Add(tc.a, tc.b); got != tc.want {
t.Fatalf("got %d want %d", got, tc.want)
}
})
}
}Bibliotecas de terceros como testify agregan aserciones y mocks; httptest de net/http/httptest es la stdlib para pruebas de manejadores.
Los equipos a menudo adoptan testify por ergonomía, pero mantienen la estructura basada en tablas y go test como el ejecutor.
| Práctica | Fortaleza | Debilidad | Mejor ajuste |
|---|---|---|---|
| Pruebas puras de stdlib | Cero dependencias, siempre compila | Comparaciones verbosas | Bibliotecas, OSS |
| Aserciones de testify | Fallos legibles | Módulo adicional | Equipos de aplicaciones grandes |
| Pruebas de integración DB pesadas | Detecta errores reales de SQL | CI lenta, inestable sin contenedores | Pocos caminos de humo |
| Fuzz + race en CI | Encuentra fallos y carreras | Costo de CPU y tiempo | Parsers sensibles a la seguridad |
Pirámide de pruebas para servicios Go: muchas pruebas rápidas en funciones puras y manejadores con httptest; menos pruebas que acceden a bases de datos reales con testcontainers; end-to-end fuera de go test o en un trabajo nocturno.
Monorepos: go test ./... en la raíz del módulo o del espacio de trabajo respeta go.work; los aciertos de caché escalan con los paquetes sin cambios.
Genéricos y basados en tablas: los parámetros de tipo no cambian el patrón: las tablas pueden contener entradas tipadas; las subpruebas todavía nombran los casos.
Puertas de cobertura: go test -coverprofile alimenta go tool cover y umbrales de CI; un alto porcentaje sin aserciones significativas es un anti-patrón conocido.
pprof explica dónde se va el tiempo en producción.La co-ubicación mantiene los ejemplos precisos cuando las APIs cambian.
go test compila ambos juntos, por lo que las pruebas fallan en tiempo de compilación cuando las firmas se mueven.
Las pruebas unitarias a nivel de paquete generalmente deberían terminar en milisegundos a pocos segundos.
Si go test ./... excede unos pocos minutos, divide las suites de integración o usa etiquetas de compilación.
No, pero es idiomático para funciones con múltiples pares de entrada/salida.
Las pruebas de ruta única pueden seguir siendo una función plana sin una tabla.
Las ejecuciones exitosas almacenan en caché los resultados por hash del paquete.
Usa go test -count=1 para deshabilitar la caché al depurar pruebas inestables.
package foo_test importa foo como lo haría un consumidor: bueno para contratos de API.
package foo puede probar ayudantes no exportados.
Prefiere interfaces pequeñas en el código de producción y fakes escritos a mano en _test.go.
Los generadores de mocks pesados son opcionales, no predeterminados.
Los ejemplos se ejecutan bajo go test y se renderizan en pkg.go.dev cuando incluyen comentarios // Output:.
Documentan el uso de la API pública, no casos extremos exhaustivos.
En trabajos dedicados o nocturnos, no en cada PR, a menos que se compare con una línea base almacenada.
Los benchmarks son ruidosos en runners compartidos.
No. El fuzzing explora entradas inesperadas; las tablas documentan el comportamiento esperado que los revisores pueden leer.
Los linters detectan problemas estáticos; las pruebas detectan comportamiento.
CI debería ejecutar ambos: consulta las puertas de calidad de linting para el orden.
sleep hace que las pruebas sean lentas e inestables bajo carga.
Usa canales, sync.WaitGroup, o control de respuesta httptest en su lugar.
Generalmente no: las pruebas pertenecen al mismo módulo que el código que ejercitan.
Los módulos e2e separados son para pruebas de despliegue de caja negra.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado Green Tea GC, go fix modernizers - verificar parche en la compilación), chi (última - verificar en la compilación), gin (última - verificar en la compilación), echo (última - verificar en la compilación), google.golang.org/grpc (última - verificar en la compilación), sigs.k8s.io/controller-runtime (última - verificar en la compilación), kubebuilder (última - verificar en la compilación), tinygo (última - verificar objetivos de placa en la compilación), wazero (última - verificar en la compilación) y golangci-lint (última - verificar conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 16 jul 2026