CodePark/ questions / Databases, Testcontainers & test data
START PRACTICINGPRACTICE
Backend question · Backend testing › Databases, Testcontainers & test data

What strategies can you use to isolate database state between tests, and what are their trade-offs?

There are three main strategies. Each one trades speed for realism or parallel safety.

Transaction per test. Begin a transaction in beforeEach. Run the test on that connection. Roll back in afterEach.

  • Pros: very fast, and it leaves nothing behind.
  • Cons: it only works if the code under test uses that same connection. It can't test commit behaviour. It can't test code that opens its own transactions, unless you map those to savepoints. It can't test concurrency across connections.

Truncate between tests. Run TRUNCATE ... RESTART IDENTITY CASCADE on every table except the migrations table.

  • Pros: simple and realistic.
  • Cons: slower with many tables. Unsafe if parallel tests share the database.

Database or schema per worker. Give each Jest worker its own database. For example, name it with JEST_WORKER_ID and clone it from a migrated template database. Still clean between tests inside it.

  • Pros: safe for parallel runs.
  • Cons: some setup cost.

Also write tests that tolerate shared data:

  • Use unique emails and ids in each test.
  • Scope assertions to the rows the test created.
  • Rollback per test is fast, but needs the same connection and can't test commits or concurrency.
  • Truncating between tests is simple but slower, and not parallel-safe in one database.
  • Use a database or schema per worker for parallel runs.
  • Use unique data in each test and scope assertions to that data.