pqxtest

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2022 License: Apache-2.0 Imports: 20 Imported by: 0

README

Go docs are here

Documentation

Overview

Package pqxtest provides functions for testing with an embedded live, lightweight, standalone Postgres instance optimized for fast setup/teardown and cleanup.

Starting, creating a database, using the database, and shutting down can all be done with:

func TestMain(m *testing.M) {
	pqxtest.TestMain(m)
}

func TestSomething(t *testing.T) {
	db := pqxtest.CreateDB(t, "CREATE TABLE foo (id INT)")
	// ... do something with db ...
	// NOTE: db will be closed automatically when t.Cleanup is called and the database will be dropped.
}

Developer Speed

Pqxtest enables a developer to go from zero to well tested, production ready code that interacts with a database in no time. This means removing much of the toil associated with configuring and running a standalone postgres instance, the can be brittle is left standing across test runs, over engineering with abundant interfaces for mocking.

Easy CI

Because pqxtest uses pqx which "embeds" a postgres into you application, CI is just "go test". No extra environment setup required. See this packages .github/workflows for an example.

No Mocks

Mocking database interactions is dangerous. It is easy to create a test that gives false positives, or can cause developers precious time hunting down a bug that doesn't exist because they're getting false negatives from the mocks (i.e. the code would work if running against an actual database).

Writing mocks and mocking code is almost always avoidable when interacting with a live database. Try pqxtest and ditch you mocking libraries and all the for-tests-only interfaces and use concrete types instead!

No global transaction

Some test libraries create a single transaction for a test and return a wrapper-driver *sql.DB that runs all queries in a test in that transaction. This is less than ideal because, like mocks, this isn't how applications work in production, so it can lead to weird behaviors and false positives. It also means you can't use those nifty driver specific functions you love. Pqxtest returns a real *sql.DB.

Speed

Pqx is fast. It is designed to give you all the benefits of writing tests against a real database without slowing you down. That means no waiting for setup and teardown after the first test run. The first "go test" takes only a second or two to cache the standalone postgres binary and initialize the data directory, but subsequent runs skip these steps, making them very fast!

Logs

Databases are created using the test name, and all logs associated with the test database are logged directly to the test t.Logf function. This provides rapid feedback and context when things go wrong. No more greping around in a shared log file.

For example, the following failing tests will log the postgres logs for their databases only:

func TestFailingInsert(t *testing.T) {
	db := pqxtest.CreateDB(t, ``)
	_, err := db.Exec(`INSERT INTO foo VALUES (1)`)
	if err != nil {
		t.Fatal(err)
	}
}

func TestFailingSelect(t *testing.T) {
	db := pqxtest.CreateDB(t, ``)
	_, err := db.Exec(`SELECT * FROM bar`)
	if err != nil {
		t.Fatal(err)
	}
}

Running ("go test") will produce:

--- FAIL: TestFailingInsert (0.03s)
    example_test.go:54: [pqx]: psql 'host=localhost port=51718 dbname=testfailinginsert_37d0bb55e5c8cb86 sslmode=disable'
    logplex.go:123: ERROR:  relation "foo" does not exist at character 13
    logplex.go:123: STATEMENT:  INSERT INTO foo VALUES (1)
    example_test.go:57: pq: relation "foo" does not exist
--- FAIL: TestFailingSelect (0.03s)
    example_test.go:62: [pqx]: psql 'host=localhost port=51718 dbname=testfailingselect_2649dda9b27d8c74 sslmode=disable'
    logplex.go:123: ERROR:  relation "bar" does not exist at character 15
    logplex.go:123: STATEMENT:  SELECT * FROM bar
    example_test.go:65: pq: relation "bar" does not exist

Tip: Try running these tests with "go test -v -pqxtest.d=2" to see more detailed logs in the tests, or set it to 3 and see even more verbose logs.

PSQL

Test databases can be accessed using the psql command line tool before they exist. Use the BlockForPSQL function to accomplish this.

No Config

Pqx starts each postgres with reasonable defaults for the most common use cases. The defaults can be overridden by setting environment variables and using flags. See below.

Environment Variables

The following environment variables are recognized:

PQX_PG_VERSION: Specifies the version of postgres to use. The default is pqx.DefaultVersion.

Flags

pqxtest recognizes the following flag:

-pqxtest.d=<level>: Sets the debug level for the Postgres instance. See Logs for more details.

Flags may be specified with go test like:

go test -v -pqxtest.d=2

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BlockForPSQL

func BlockForPSQL(t testing.TB)

BlockForPSQL logs the psql commands for connecting to all databases created by CreateDB in a test, and blocks the current goroutine allowing the user to interact with the databases.

As a special case, if testing.Verbose is false, it logs to stderr to avoid silently hanging the tests.

BreakForPSQL is intended for debugging only and not to be left in tests.

Example Usage:

 func TestSomething(t *testing.T) {
 	db := pqxtest.CreateDB(t, "CREATE TABLE foo (id INT)")
	defer pqxtest.BlockForPSQL(t) // will run even in the face of t.Fatal/Fail.
 	// ... do something with db ...
 }

func CreateDB

func CreateDB(t testing.TB, schema string) *sql.DB

CreateDB creates and returns a database using the shared Postgres instance. The database will automatically be cleaned up just before the test ends.

All logs associated with the database will be written to t.Logf.

func DSN

func DSN() string

DSN returns the main dsn for the running postgres instance. It must only be call after a call to Start.

func DSNForTest added in v0.2.0

func DSNForTest(t testing.TB) string

DSNForTest returns the dsn for the first test database created using t. It must only be called after a call to CreateDB.

func Shutdown

func Shutdown()

Shutdown shuts down the shared Postgres instance.

func Start

func Start(timeout time.Duration, debugLevel int)

Start starts a Postgres instance. The version used is determined by the PQX_PG_VERSION environment variable if set, otherwise pqx.DefaultVersion is used.

The Postgres instance is started in a temporary directory named after the current working directory and reused across runs.

func TestMain

func TestMain(m *testing.M)

TestMain is a convenience function for running tests with a live Postgres instance. It starts the Postgres instance before calling m.Run, and then calls Shutdown after.

Users that need do more in their TestMain, can use it as a reference.

Types

This section is empty.

Jump to

Keyboard shortcuts

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