testenv

module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 8, 2026 License: MIT

README

testenv

A comprehensive Go framework for managing PostgreSQL test environments with container support, connection pooling, and automatic migrations.

Overview

testenv provides a clean, composable system for setting up and managing database environments in tests and production code. It offers flexible connection management with support for Docker containers, connection pooling, multiple reuse strategies, and automatic migration application.

Features

  • Environment Management: High-level abstractions for managing database connections
  • Container Support: Seamless integration with testcontainers for isolated test environments
  • Connection Pooling: Efficient connection management via pgx
  • Multiple Reuse Strategies:
    • Create new database per connection (full isolation)
    • Create new schema per connection (good isolation, better performance)
    • Raw connection (no additional isolation)
  • Automatic Migrations: Apply migrations automatically when connecting
  • Standard Library Compatibility: Works with both pgx and standard *sql.DB
  • Thread Safe: All components are safe for concurrent use
  • Test Helpers: Built-in utilities for test cleanup and lifecycle management

Installation

go get go.amidman.dev/testenv

Quick Start

Basic Usage
package main

import (
    "context"
    "fmt"
    "testing"
    
    "go.amidman.dev/testenv/dbenv"
    "go.amidman.dev/testenv/postgresenv"
)

func TestWithDatabase(t *testing.T) {
    t.Parallel()
    
    // Create a connector
    connector := postgresenv.NewConnector(
        postgresenv.WithHost("localhost"),
        postgresenv.WithPort(5432),
        postgresenv.WithDatabase("testdb"),
        postgresenv.WithUser("testuser"),
        postgresenv.WithPassword("testpass"),
    )
    
    // Create environment with reuse strategy
    env := postgresenv.New(
        postgresenv.WithConnectorReuseOptions(func() (*postgresenv.Connector, error) {
            return connector, nil
        }),
        postgresenv.WithReuseStrategy(&postgresenv.ReuseStrategyCreateNewDB{}),
    )
    
    // Connect - automatically creates a new isolated database
    pool, err := env.Connect(t.Context())
    if err != nil {
        t.Fatal(err)
    }
    defer pool.Close()
    
    // Use the pool for database operations
    var count int
    err = pool.Pool.QueryRow(t.Context(), "SELECT COUNT(*) FROM users").Scan(&count)
    if err != nil {
        t.Fatal(err)
    }
    
    fmt.Printf("User count: %d\n", count)
}
Using with dbenv.UseForTesting

For simpler test setup with automatic cleanup:

import (
    "testing"
    
    "go.amidman.dev/testenv/dbenv"
)

func TestWithDbenvHelper(t *testing.T) {
    t.Parallel()
    
    // Create environment
    env := createTestEnvironment()
    
    // Get database connection - automatically closed after test
    db := dbenv.UseForTesting(t, env)
    
    // Use standard *sql.DB
    var count int
    err := db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count)
    require.NoError(t, err)
    
    assert.Equal(t, 0, count)
}
With Migrations
import (
    "testing"
    
    "go.amidman.dev/testenv/dbenv"
    "go.amidman.dev/testenv/dbenv/migrations"
)

func TestWithMigrations(t *testing.T) {
    t.Parallel()
    
    // Create environment
    env := createBaseEnvironment()
    
    // Define migrations as an option
    migration := migrations.Queries(
        "CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT)",
        "CREATE INDEX idx_users_name ON users(name)",
    )
    
    // Connect with migrations applied via option
    db := dbenv.UseForTesting(t, env, migration)
    
    // Database now has users table
    _, err := db.Exec("INSERT INTO users (name) VALUES ($1)", "Alice")
    require.NoError(t, err)
}
Standard Library Compatibility
// Create stdlib-compatible environment
stdlibEnv := postgresenv.NewStdlib(env)

// Connect using standard library
db, err := stdlibEnv.Connect(ctx)
if err != nil {
    return err
}
defer db.Close()

// Use standard *sql.DB
rows, err := db.QueryContext(ctx, "SELECT * FROM users")

Package Structure

  • dbenv: Core utilities for using database environments
  • dbenv/migrations: Migration management utilities
  • postgresenv: PostgreSQL-specific environment management
  • reuse: Generic resource reuse mechanism

Reuse Strategies

ReuseStrategyCreateNewDB

Creates a new database for each connection. Provides complete isolation but may be slower due to database creation overhead.

env := postgresenv.New(
    postgresenv.WithReuseStrategy(&postgresenv.ReuseStrategyCreateNewDB{
        NewDBName: func() string {
            return "testdb_" + uuid.New().String()
        },
    }),
)
ReuseStrategyCreateNewSchema

Creates a new schema in an existing database. Good isolation with better performance.

env := postgresenv.New(
    postgresenv.WithReuseStrategy(&postgresenv.ReuseStrategyCreateNewSchema{
        DB: "mydb",
        NewSchemaName: func() string {
            return "testschema_" + uuid.New().String()
        },
    }),
)

Documentation

For detailed documentation, see the package docs:

License

MIT License. See LICENSE for details.

Directories

Path Synopsis
migrations
Package migrations provides utilities for managing database migrations in test environments.
Package migrations provides utilities for managing database migrations in test environments.
migrations/goose
Package goosemigrations provides a goose-based migration adapter for the migrations package.
Package goosemigrations provides a goose-based migration adapter for the migrations package.
Package postgresenv provides PostgreSQL environment management for testing.
Package postgresenv provides PostgreSQL environment management for testing.
containers
Package containers provides Docker container management for PostgreSQL test environments.
Package containers provides Docker container management for PostgreSQL test environments.
Package reuse provides a generic resource reuse mechanism with automatic lifecycle management.
Package reuse provides a generic resource reuse mechanism with automatic lifecycle management.

Jump to

Keyboard shortcuts

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