Pruebas en Go: unit, integration, e2e — guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: Por qué es importante realizar pruebas en Go

Go (Golang) es un lenguaje que desde su diseño se ha enfocado en la simplicidad, el rendimiento y la confiabilidad. El paquete integrado testing y herramientas potentes como go test hacen que escribir pruebas sea una parte integral del desarrollo. Sin pruebas de calidad, incluso el código más elegante se convierte eventualmente en un sistema "frágil" donde un cambio lo rompe todo.

En este artículo, analizaremos tres niveles clave de pruebas: unitarias, de integración y e2e (de extremo a extremo). Aprenderás en qué se diferencian, cuándo aplicarlas y cómo escribir pruebas efectivas en Go. El material será útil tanto para principiantes como para desarrolladores experimentados que buscan sistematizar sus conocimientos.



1. Pruebas Unitarias

Las pruebas unitarias son la base de la pirámide de pruebas. Verifican el funcionamiento de funciones, métodos o módulos individuales de forma aislada de las dependencias externas (bases de datos, red, sistema de archivos).



Principios Básicos de las Pruebas Unitarias en Go

  • Aislamiento: El código que se está probando no debe depender de servicios externos.
  • Velocidad: Las pruebas unitarias se ejecutan en milisegundos.
  • Determinismo: El resultado de la prueba no debe cambiar de una ejecución a otra.


Ejemplo de una Prueba Unitaria Simple

Supongamos que tenemos una función para sumar dos números:

// math.gopackage math

func Add(a, b int) int { return a + b}

La prueba para esta función se vería así:

// math_test.gopackage math

import "testing"

func TestAdd(t *testing.T) { result := Add(2, 3) expected := 5

if result != expected { t.Errorf("Add(2, 3) = %d; want %d", result, expected) }}

La prueba se ejecuta con el comando: go test ./...



Pruebas Basadas en Tablas

La comunidad de Go prefiere las pruebas basadas en tablas para verificar múltiples casos:

func TestAddTable(t *testing.T) {    tests := []struct {        a, b, expected int    }{        {1, 1, 2},        {0, 0, 0},        {-1, 1, 0},        {100, 200, 300},    }

for _, tt := range tests { result := Add(tt.a, tt.b) if result != tt.expected { t.Errorf("Add(%d, %d) = %d; want %d", tt.a, tt.b, result, tt.expected) } }}

Consejo: Usa t.Run() para crear pruebas anidadas con nombres claros — esto mejora la legibilidad del informe.



2. Pruebas de Integración

Las pruebas de integración verifican la interacción entre los componentes del sistema: base de datos, API, servicios externos. A diferencia de las pruebas unitarias, aquí se utilizan dependencias reales (o casi reales).



Características de las Pruebas de Integración en Go

  • A menudo requieren configuración del entorno (por ejemplo, una base de datos de prueba).
  • Pueden usar build tags para separar las pruebas unitarias de las de integración.
  • Se ejecutan más lentamente, por lo que se ejecutan por separado.


Ejemplo: Prueba de Operaciones de Base de Datos (PostgreSQL)

Creemos un archivo con el build tag integration:

// db_test.go//go:build integration

package db

import ( "database/sql" "testing")

func TestSaveUser(t *testing.T) { // Conectar a la base de datos de prueba dsn := "host=localhost user=test password=test dbname=testdb sslmode=disable" db, err := sql.Open("postgres", dsn) if err != nil { t.Fatalf("failed to connect to db: %v", err) } defer db.Close()

// Limpiar datos antes de la prueba _, _ = db.Exec("TRUNCATE TABLE users")

// Ejecutar la operación que se está probando user := User{Name: "Alice", Email: "alice@example.com"}

Blogs

Book Recommendations