package test import ( "context" "log/slog" "testing" "time" "gitea.michaelthomson.dev/mthomson/habits/internal/migrate" pgxuuid "github.com/jackc/pgx-gofrs-uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/modules/postgres" "github.com/testcontainers/testcontainers-go/wait" ) type TestDatabase struct { Db *pgxpool.Pool container testcontainers.Container } func NewTestDatabase(tb testing.TB) *TestDatabase { tb.Helper() ctx := context.Background() // create container postgresContainer, err := postgres.Run(ctx, "postgres:16-alpine", postgres.WithDatabase("todo"), postgres.WithUsername("todo"), postgres.WithPassword("password"), testcontainers.WithWaitStrategy( wait.ForLog("database system is ready to accept connections"). WithOccurrence(2). WithStartupTimeout(5*time.Second)), ) if err != nil { tb.Fatalf("Failed to create postgres container, %v", err) } connectionString, err := postgresContainer.ConnectionString(ctx) if err != nil { tb.Fatalf("Failed to get connection string: %v", err) } dbconfig, err := pgxpool.ParseConfig(connectionString) if err != nil { tb.Fatalf("Failed to create db config: %v", err) } dbconfig.AfterConnect = func(ctx context.Context, conn *pgx.Conn) error { pgxuuid.Register(conn.TypeMap()) return nil } // create db pool db, err := pgxpool.NewWithConfig(context.Background(), dbconfig) if err != nil { tb.Fatalf("Failed to open db pool: %v", err) } migrate.Migrate(slog.Default(), db) return &TestDatabase{ Db: db, container: postgresContainer, } } func (tdb *TestDatabase) TearDown() { _ = tdb.container.Terminate(context.Background()) }