pgrx

package module
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 25, 2025 License: MIT Imports: 20 Imported by: 0

README

PGRx - Go PostgreSQL Integration Test Extension for groat testing suite

codecov Go Report Card License

PGRx is a lightweight extension for groat that makes integration testing with PostgreSQL in Go clean, simple, and efficient. It leverages testcontainers-go to provide isolated PostgreSQL instances for your tests.

Features

  • 🚀 Simple API - Bootstrap a PostgreSQL container with minimal code
  • 🧪 Test Isolation - Each test gets its own database, allowing parallel test execution
  • 🔄 Migrations Support - Run SQL migrations automatically before tests
  • 🔧 Highly Configurable - Customize everything from container image to connection pool parameters
  • 💉 Dependency Injection - Easily inject database connections into your test structures

Installation

go get github.com/godepo/pgrx

Quick Start

For example, we have system under test something like this:


type Repository struct {
	db *pgxpool.Pool
}

func New(db *pgxpool.Pool) *Repository {
	return &Repository{db: db}
}

Make file main_test.go and add this code in file for support groat conventions:

type State struct{
	// groat states variables
}

// This struct contains fixtured tests dependencies
type Deps struct {
    DB *pgxpool.Pool `groat:"pgxpool"` // inject connection pool to this field after creation
	Config *pgxpool.Config `groat:"pgxconfig"` // inject pgx config to this field after creation
}

for work instantiate test add in main_test.go file this code for run postgresql container:

// global state for testing package control all runed integrated containers by groat test suite convention
var suite *integration.Container[Deps, State, *Repostitory]

// By groat convention contain fixture constructor for each isolated test. For each test constructed self pool, database 
// and run migrations. 
func mainProvider(t *testing.T) *groat.Case[Deps, State, *Instance] {
    tcs := groat.New[Deps, State, *Instance](t, func(t *testing.T, deps Deps) *Repository {
        return New(deps.DB) // take pool from injected dependencies field and pass to SUT constructor
    })
    return tcs
}

// Instantiate package suite with single postgresql container for all test.
func TestMain(m *testing.M) {
    suite = integration.New[Deps, State, *Repository](m, mainProvider,
        pgrx.New[Deps](
            pgrx.WithContainerImage("docker.io/postgres:16"),
            pgrx.WithMigrationsPath("./sql"),
        ),
    )
    os.Exit(suite.Go())
}

Make file with your tests cases, by example file cases_test.go, and start writing integration tests:

func TestRepository_Create(t *testing.T) {
    tcs := suite.Case(t) // take new instantiated groat test case with constructed SUT (Repository) and worked *Pool.
	
	// write your tests case and use groat and pgrx like fixture, or write groat-like tests below. 
}

How It Works

Under the hood, PGRx:

  1. Starts a PostgreSQL container using testcontainers-go
  2. Creates a base database for management operations
  3. For each test call:
    • Creates a new database with a unique name in postgresql.
    • Runs migrations on the new database.
    • Creates a connection pool for the new database.
    • Injects the connection pool into your test structure.
    • Injects the configuration structure into your test dependencies.

This approach ensures that each test has its own isolated database, making tests reliable and allowing them to run in parallel.

Requirements

  • Go 1.18+ (for generics support)
  • Docker (for running the PostgreSQL containers)

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrRequireNamespacePrefixForHostedDB = errors.New("hosted db requires namespace prefix")

Functions

func New

func New[T any](all ...Option) integration.Bootstrap[T]

Types

type Container

type Container[T any] struct {
	// contains filtered or unexported fields
}

func (*Container[T]) Injector

func (c *Container[T]) Injector(t *testing.T, to T) T

type DB

type DB interface {
	Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error)
}

type Migrator

type Migrator func(ctx context.Context, migratorConfig MigratorConfig) error

func PlainMigrator

func PlainMigrator(fs afero.Fs, path string) (Migrator, error)

type MigratorConfig

type MigratorConfig struct {
	DBName   string
	Pool     DB
	Path     string
	UserName string
}

type Option

type Option func(*config)

func WithContainerImage

func WithContainerImage(image string) Option

WithContainerImage override initial container image for run postgresql instance, by default using value 'postgres:16'.

func WithContainerImageEnv

func WithContainerImageEnv(env string) Option

WithContainerImageEnv override ENV contained container image name, by default using GROAT_I9N_PG_IMAGE.

func WithDBName

func WithDBName(dbName string) Option

WithDBName override the initial database for check correct migrationsPath process by default using value 'test'.

func WithDeadline

func WithDeadline(deadline time.Duration) Option

WithDeadline override the initial timeout for bootstrap container, by default used 5 seconds deadline.

func WithFileSystem

func WithFileSystem(fs afero.Fs) Option

func WithHostedNamespace added in v0.0.5

func WithHostedNamespace(ns string) Option

func WithMigrationsPath

func WithMigrationsPath(path string) Option

WithMigrationsPath set default path to migrations files.

func WithMigrator

func WithMigrator(migrator Migrator) Option

WithMigrator override default migration func for pgx pool by default used plain sql files in directory.

func WithPassword

func WithPassword(password string) Option

WithPassword override the initial password of the user to be created when the container starts as superuser by default using value 'test'.

func WithPoolConfigInjectLabel added in v0.0.4

func WithPoolConfigInjectLabel(label string) Option

func WithPoolInjectLabel added in v0.0.4

func WithPoolInjectLabel(label string) Option

func WithPoolMaxConnections

func WithPoolMaxConnections(maxCons int32) Option

WithPoolMaxConnections override default number of pgx pool max connections by default used 8.

func WithPoolMaxIdleTime

func WithPoolMaxIdleTime(maxIdleTime time.Duration) Option

WithPoolMaxIdleTime override default number of pgx pool min connections by default used one minute.

func WithPoolMinConnections

func WithPoolMinConnections(minCons int32) Option

WithPoolMinConnections override default number of pgx pool min connections by default used 2.

func WithUserName

func WithUserName(userName string) Option

WithUserName override initial username of the user to be created when the container starts. By default, using value 'test'.

type PostgresContainer added in v0.0.2

type PostgresContainer interface {
	ConnectionString(ctx context.Context, args ...string) (string, error)
	Terminate(ctx context.Context, opts ...testcontainers.TerminateOption) error
}

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL