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:
CustomerRepoTestSuiteextiendesuite.Suitee incluye campos compartidos en múltiples pruebas.SetupSuite()se ejecuta una vez antes de todas las pruebas. Llama aCreatePostgresContainer(suite.T(), ...)que gestiona el registro de la limpieza automáticamente medianteCleanupContainer, por lo que no es necesario unTearDownSuite().TestCreateCustomer()utilizarequire.NoError()para la operación de creación (falla de inmediato si hay un error) yassert.NotNil()para la verificación del ID.TestGetCustomerByEmail()utilizarequire.NoError()y luego realiza aserciones sobre los valores devueltos.TestCustomerRepoTestSuite(t *testing.T)ejecuta la suite de pruebas cuando ejecutasgo test.
TipPara 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.