Compartir comentarios
Las respuestas se generan en base a la documentación.

Reutiliza contenedores con suites de pruebas

En la sección anterior, viste cómo levantar un contenedor de Docker de Postgres para una sola prueba. Pero a menudo tienes múltiples pruebas en un solo archivo, y es posible que desees reutilizar el mismo contenedor de Docker de Postgres para todas ellas.

Puedes utilizar el paquete testify suite para implementar acciones comunes de configuración (setup) y desmontaje (teardown) de pruebas.

Extrae la configuración del contenedor

Primero, extrae la lógica de creación de PostgresContainer en un archivo separado llamado testhelpers/containers.go:

package testhelpers

import (
	"context"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/require"
	"github.com/testcontainers/testcontainers-go"
	"github.com/testcontainers/testcontainers-go/modules/postgres"
)

type PostgresContainer struct {
	*postgres.PostgresContainer
	ConnectionString string
}

func CreatePostgresContainer(t *testing.T, ctx context.Context) *PostgresContainer {
	t.Helper()

	ctr, err := postgres.Run(ctx,
		"postgres:16-alpine",
		postgres.WithInitScripts(filepath.Join("..", "testdata", "init-db.sql")),
		postgres.WithDatabase("test-db"),
		postgres.WithUsername("postgres"),
		postgres.WithPassword("postgres"),
		postgres.BasicWaitStrategies(),
	)
	testcontainers.CleanupContainer(t, ctr)
	require.NoError(t, err)

	connStr, err := ctr.ConnectionString(ctx, "sslmode=disable")
	require.NoError(t, err)

	return &PostgresContainer{
		PostgresContainer: ctr,
		ConnectionString:  connStr,
	}
}

En containers.go, PostgresContainer extiende el PostgresContainer de testcontainers-go para proporcionar un acceso fácil a ConnectionString. La función CreatePostgresContainer() acepta *testing.T como su primer parámetro, llama a t.Helper() para que los fallos de prueba apunten al llamador y utiliza testcontainers.CleanupContainer() para registrar la limpieza automática.

Escribe la suite de pruebas

Crea customer/repo_suite_test.go e implementa pruebas para crear un cliente y obtener un cliente por correo electrónico utilizando el paquete testify suite:

package customer

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/stretchr/testify/suite"
	"github.com/testcontainers/testcontainers-go-demo/testhelpers"
)

type CustomerRepoTestSuite struct {
	suite.Suite
	pgContainer *testhelpers.PostgresContainer
	repository  *Repository
	ctx         context.Context
}

func (suite *CustomerRepoTestSuite) SetupSuite() {
	suite.ctx = context.Background()
	suite.pgContainer = testhelpers.CreatePostgresContainer(suite.T(), suite.ctx)

	repository, err := NewRepository(suite.ctx, suite.pgContainer.ConnectionString)
	require.NoError(suite.T(), err)
	suite.repository = repository
}

func (suite *CustomerRepoTestSuite) TestCreateCustomer() {
	t := suite.T()

	customer, err := suite.repository.CreateCustomer(suite.ctx, Customer{
		Name:  "Henry",
		Email: "[email protected]",
	})
	require.NoError(t, err)
	assert.NotNil(t, customer.Id)
}

func (suite *CustomerRepoTestSuite) TestGetCustomerByEmail() {
	t := suite.T()

	customer, err := suite.repository.GetCustomerByEmail(suite.ctx, "[email protected]")
	require.NoError(t, err)
	assert.Equal(t, "John", customer.Name)
	assert.Equal(t, "[email protected]", customer.Email)
}

func TestCustomerRepoTestSuite(t *testing.T) {
	suite.Run(t, new(CustomerRepoTestSuite))
}

Esto es lo que hace el código:

  • CustomerRepoTestSuite extiende suite.Suite e incluye campos compartidos en múltiples pruebas.
  • SetupSuite() se ejecuta una vez antes de todas las pruebas. Llama a CreatePostgresContainer(suite.T(), ...) que gestiona el registro de la limpieza automáticamente mediante CleanupContainer, por lo que no es necesario un TearDownSuite().
  • TestCreateCustomer() utiliza require.NoError() para la operación de creación (falla de inmediato si hay un error) y assert.NotNil() para la verificación del ID.
  • TestGetCustomerByEmail() utiliza require.NoError() y luego realiza aserciones sobre los valores devueltos.
  • TestCustomerRepoTestSuite(t *testing.T) ejecuta la suite de pruebas cuando ejecutas go test.
Tip

Para los propósitos de esta guía, las pruebas no restablecen los datos en la base de datos. En la práctica, es una buena idea restablecer la base de datos a un estado conocido antes de ejecutar cada prueba.