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 ¶
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 ¶
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
DSNForTest returns the dsn for the first test database created using t. It must only be called after a call to CreateDB.
Types ¶
This section is empty.