Skip to content

Better tests with containers

Managing state is hard. Managing database state is even harder. And coordinating state within a test suite is just always a bad time.

But it doesn't have to be this way!

There is a fantastic Go package called ory/dockertest that allows you to spin up ephemeral docker containers. It'll work both locally (assuming you have Docker installed) and in your Continuous Integration (CI) pipelines.

After applying thousands of migrations in production we know goose is production-ready and does the right thing. But we have plans to add more functionality to goose, and integration tests are a welcome addition to the goose test-suie.

In a recent goose release (PR#276) we added container-based database tests. These tests spin up a fresh database per test. Yes, that's right, we're talking dozens of containers.

After each test is completed the container is cleaned up, something like this:

t.Cleanup(func() {
    if err := pool.Purge(container); err != nil {
        log.Printf("failed to purge resource: %v", err)
    }
})

For integration tests this is perfect. We can spin up a fresh lightweight container for each test, such as postgres:14-alpine, and not worry about tests stomping on each other or having to coordinate state between tests.

The entire thing is fast! Where tests run in parallel using t.Parallel() and the entire integration test-suite run in about 6-7s (for postgres:14-alpine).

Check it out..

+--------+---------+----------------------------+---------+
| STATUS | ELAPSED |            TEST            | PACKAGE |
+--------+---------+----------------------------+---------+
| PASS   |    5.77 | TestMigrateOutOfOrderDown  | e2e     |
| PASS   |    5.54 | TestNowAllowMissingUpByOne | e2e     |
| PASS   |    5.28 | TestAllowMissingUp         | e2e     |
| PASS   |    4.60 | TestAllowMissingUpByOne    | e2e     |
| PASS   |    4.48 | TestNotAllowMissing        | e2e     |
| PASS   |    4.39 | TestMigrateUpTo            | e2e     |
| PASS   |    4.31 | TestMigrateUpByOne         | e2e     |
| PASS   |    3.69 | TestMigrateUp              | e2e     |
| PASS   |    2.30 | TestMigrateFull            | e2e     |
+--------+---------+----------------------------+---------+

+--------+---------+---------------------------------------+
| STATUS | ELAPSED |                PACKAGE                |
+--------+---------+---------------------------------------+
| PASS   | 6.12s   | github.com/pressly/goose/v3/tests/e2e |
+--------+---------+---------------------------------------+

So, next time you need a database in your containers