Hacker News new | ask | show | jobs
by kakwa_ 1230 days ago
We do that too, in fact it's not only the DB that run in docker, but the whole build + CI process.

Our overall strategy is to create a master "test" DB with a test dataset, and for each test, copy this master DB to a test specific DB (CREATE DATABASE <testdb> TEMPLATE <master>) so that tests can run in parallel without interfering with each other and without the significant overhead of a "from scratch" DB initialization.

For schema migrations, we build the "branch/PR" version and the "main" version, then we check that 'init DB with "main" + migration with the "branch/PR" version' results in the same schema as 'init the DB directly with the "branch/PR" version' using apgdiff.

This strategy could probably be extended to migrating from every older version by building each tag, but we don't have that need.

We could also probably improve checks on the data itself however as for now, we only check the schemas.

Few things to note:

* it's still possible to run the tests outside of docker and use a local DB instead with some light setup (it's faster than running everything in docker when developing)

* docker argument --tmpfs <dir/of/db> is quite good, assuming you have enough ram for your dataset

* few configuration tweaks on the DB, like max connection might be necessary.

Overall, we are quite happy with this setup as it permits to implement end to end integration tests quite easily without spending too much time mocking dependencies.

As a general pattern, I find instantiating dependencies internal to your service (like a DB or Queue) to be the way to go, with mocking only for external dependencies (like external APIs) or exceptionally to reach a specific code branch (specially error handling sections).