testdb

package module
v0.0.0-...-a3705a3 Latest Latest
Warning

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

Go to latest
Published: Oct 15, 2022 License: MIT Imports: 8 Imported by: 2

README

Go Reference

testdb

testdb is a Go package that manages access to multiple PostgreSQL databases with to enable parallel testing.

Integration tests often need to run with exclusive access to a database. i.e. Multiple tests cannot use the same database at the same time.

In addition, when an application has multiple packages that each have integration tests, then running go test ./... will run the package tests in parallel by default.

testdb uses the PostgreSQL server to manage exclusive access to databases even when the tests are running in parallel in different processes.

Preparing the Databases

testdb requires that the testdb management data be loaded and test databases already be created and prepared before the it can be used..

See setup_test_databases.sql for an example setup script.

Example Usage

Typically, a package should have one global manager. This test manager should be created in TestMain().

var TestDBManager *testdb.Manager

func TestMain(m *testing.M) {
	TestDBManager = testutil.InitTestDBManager(m)
	os.Exit(m.Run())
}

To allow for creating test managers in multiple packages the actual creation of the test manager is in contained in a function in a separate package. e.g.

// InitTestDBManager performs the standard initialization of a *testdb.Manager. It requires a *testing.M to
// ensure it is only called by TestMain. If something fails it calls os.Exit(1).
func InitTestDBManager(*testing.M) *testdb.Manager {
	manager := &testdb.Manager{
		AfterAcquireDB: func(t testing.TB, db *testdb.DB, conn *pgx.Conn) {
			// Do some sort of setup or initial testing.

			t.Cleanup(func() {
				// Do some cleanup or final testing.
			})
		},
		ResetDB: func(ctx context.Context, conn *pgx.Conn) error {
			// Do whatever is necessary to restore the database to pristine condition
		},
	}

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()
	err := manager.Connect(ctx, fmt.Sprintf("dbname=%s", os.Getenv("TEST_DATABASE")))
	if err != nil {
		fmt.Println("failed to init testdb.Manager:", err)
		os.Exit(1)
	}

	return manager
}

The actual test could be something like this:

func TestSomethingWithExclusiveDatabaseAccess(t *testing.T) {
	t.Parallel()

	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	t.Cleanup(cancel)

	conn := TestDBManager.AcquireDB(t, ctx).Connect(t, ctx)

	// Run tests with conn. No defer / cleanup is necessary as testdb calls t.Cleanup internally.
}

Reset / Cleanup Database

testdb does not provide any functionality to reset or cleanup the database between tests. That must be provided in the ResetDB hook by the caller.

https://github.com/jackc/pgundolog may be useful to provide this functionality in an application-agnostic manner.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DB

type DB struct {
	// contains filtered or unexported fields
}

DB represents exclusive access to a database.

func (*DB) Connect

func (db *DB) Connect(t testing.TB, ctx context.Context) *pgx.Conn

Connect establishes a single connection to db. If the test only needs a single connection and does not have any transactional behavior of its own then prefer TxConnect as it may be faster. A t.Cleanup function is registered to close the connection at the end of the test so no explicit cleanup is required.

func (*DB) DBName

func (db *DB) DBName() string

func (*DB) PoolConnect

func (db *DB) PoolConnect(t testing.TB, ctx context.Context) *pgxpool.Pool

PoolConnect establishes a connection pool to db. A t.Cleanup function is registered to release the pool at the end of the test so no explicit cleanup is required.

func (*DB) TxConnect

func (db *DB) TxConnect(t testing.TB, ctx context.Context) pgx.Tx

TxConnect establishes a single connection to db and starts a transaction. With pgundolog the transaction is unnecesary but tests may run faster when run in a transaction due to writes not needing to actually be durable until commit (which never will happen). A t.Cleanup function is registered to close the connection at the end of the test so no explicit cleanup is required.

type Manager

type Manager struct {

	// AfterAcquireDB is called after a DB is acquired. It can be used to do setup such as loading fixtures or canaries.
	// t.Cleanup can be used to register cleanup or final tests such as checking canary health. conn is the maintenance
	// connection to db.
	AfterAcquireDB func(t testing.TB, db *DB, conn *pgx.Conn)

	// MakeConnConfig is used by DBs created by this Manager to configure connections. It returns a *pgx.ConnConfig for
	// suitable for connecting to connConfig.Database. connConfig is what would have been used if MakeConnConfig was nil.
	// connConfig may be modified and returned or an entirely new *pgx.ConnConfig may be created.
	//
	// connConfig is a copy of the *pgx.ConnConfig used to establish the manager connection, but with the Database field
	// replaced with the actual database to be connected to and with a OnNotice handler that logs PostgreSQL notices to
	MakeConnConfig func(t testing.TB, connConfig *pgx.ConnConfig) *pgx.ConnConfig

	// AfterConnect is called by DB.Connect after a connection is established. It is also used by any pool returned from
	// DB.ConnectPool. If an error is returned the connection will be closed.
	AfterConnect func(ctx context.Context, conn *pgx.Conn) error

	// ResetDB is called to reset a database to pristine condition.
	ResetDB func(ctx context.Context, conn *pgx.Conn) error
	// contains filtered or unexported fields
}

Manager manages access to test databases. Connect or ConnectConfig must be called before any other methods.

func (*Manager) AcquireDB

func (m *Manager) AcquireDB(t testing.TB, ctx context.Context) *DB

AcquireDB acquires a DB for exclusive use. A t.Cleanup function is registered to release the database at the end of the test so no explicit cleanup is required.

func (*Manager) Connect

func (m *Manager) Connect(ctx context.Context, connStr string) error

Connect establishes m's connection to the database with a connection string.

func (*Manager) ConnectConfig

func (m *Manager) ConnectConfig(ctx context.Context, connConfig *pgx.ConnConfig) error

ConnectConfig establishes m's connection to the database with a connection config.

Jump to

Keyboard shortcuts

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