- Introduced a new `.env.test.example` file for integration test configuration. - Added a `Makefile` to streamline test commands for unit and integration tests. - Implemented an integration testing harness with support for PostgreSQL, MinIO, and Redis using testcontainers. - Created a suite of integration tests covering health checks and user management functionalities. - Enhanced CI workflow to include integration tests with necessary environment variables.
119 lines
2.7 KiB
Go
119 lines
2.7 KiB
Go
//go:build integration
|
|
|
|
package integrationtest
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/testcontainers/testcontainers-go"
|
|
"github.com/testcontainers/testcontainers-go/modules/minio"
|
|
"github.com/testcontainers/testcontainers-go/modules/postgres"
|
|
"github.com/testcontainers/testcontainers-go/wait"
|
|
)
|
|
|
|
type infra struct {
|
|
pgContainer testcontainers.Container
|
|
minioContainer testcontainers.Container
|
|
miniredis *miniredis.Miniredis
|
|
dbURL string
|
|
s3Endpoint string
|
|
s3AccessKey string
|
|
s3SecretKey string
|
|
redisAddr string
|
|
}
|
|
|
|
func sharedInfra(ctx context.Context, env Env) (*infra, error) {
|
|
return startInfra(ctx, env)
|
|
}
|
|
|
|
func startInfra(ctx context.Context, env Env) (*infra, error) {
|
|
out := &infra{
|
|
dbURL: env.DBURL,
|
|
s3Endpoint: env.S3Endpoint,
|
|
s3AccessKey: env.S3AccessKey,
|
|
s3SecretKey: env.S3SecretKey,
|
|
redisAddr: env.RedisAddr,
|
|
}
|
|
|
|
if out.dbURL == "" {
|
|
pg, err := postgres.Run(ctx,
|
|
"postgres:16-alpine",
|
|
postgres.WithDatabase("ultidb_test"),
|
|
postgres.WithUsername("ulti"),
|
|
postgres.WithPassword("test"),
|
|
testcontainers.WithWaitStrategy(
|
|
wait.ForLog("database system is ready to accept connections").
|
|
WithOccurrence(2).
|
|
WithStartupTimeout(60*time.Second),
|
|
),
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("postgres container: %w", err)
|
|
}
|
|
out.pgContainer = pg
|
|
connStr, err := pg.ConnectionString(ctx, "sslmode=disable")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("postgres connection string: %w", err)
|
|
}
|
|
out.dbURL = connStr
|
|
}
|
|
|
|
if out.redisAddr == "" {
|
|
mr, err := miniredis.Run()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("miniredis: %w", err)
|
|
}
|
|
out.miniredis = mr
|
|
out.redisAddr = mr.Addr()
|
|
}
|
|
|
|
if out.s3Endpoint == "" {
|
|
m, err := minio.Run(ctx,
|
|
"minio/minio:latest",
|
|
minio.WithUsername(env.S3AccessKey),
|
|
minio.WithPassword(env.S3SecretKey),
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("minio container: %w", err)
|
|
}
|
|
out.minioContainer = m
|
|
host, err := m.ConnectionString(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("minio endpoint: %w", err)
|
|
}
|
|
out.s3Endpoint = host
|
|
}
|
|
|
|
if out.s3AccessKey == "" {
|
|
out.s3AccessKey = "ultiadmin"
|
|
}
|
|
if out.s3SecretKey == "" {
|
|
out.s3SecretKey = "changeme123"
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func (i *infra) Close(ctx context.Context) {
|
|
if i == nil {
|
|
return
|
|
}
|
|
if i.miniredis != nil {
|
|
i.miniredis.Close()
|
|
}
|
|
if i.pgContainer != nil {
|
|
_ = i.pgContainer.Terminate(ctx)
|
|
}
|
|
if i.minioContainer != nil {
|
|
_ = i.minioContainer.Terminate(ctx)
|
|
}
|
|
}
|
|
|
|
func normalizeEndpoint(endpoint string) string {
|
|
return strings.TrimPrefix(strings.TrimPrefix(endpoint, "http://"), "https://")
|
|
}
|