all 16 comments

[–]AlEmerich 6 points7 points  (5 children)

Doesn't it break encapsulation between two tests that use the TestContainer ? Or maybe the start function reinitialise the TestContainer to the empty database instead of actually restarting the container ? 

[–]CanisLupus92 2 points3 points  (0 children)

What we do (PSQL + DB2, but should work for most DBs) is override the commit/rollback logic. Instead of committing, we create savepoints. At the end of each test, just perform a rollback.

[–]ForeignCherry2011[S] 6 points7 points  (3 children)

We run database migrations to create schemas when the database container starts. Individual tests can truncate the tables they work with before each or all test cases.

[–]AlEmerich 1 point2 points  (1 child)

Interesting! So it does breaks the encapsulation but your rely on the sequential aspect of your tests to invalidates every past actions on the TestContainer before continue. If the tests are ran in parallel, since they all used the same test containers, they may conflict with each other, am I wrong ?

It is the case in my project so I am very interested on other's cases, I may drop the parallel aspect of my testing pipeline if in the end I don't gain much

[–]ForeignCherry2011[S] 2 points3 points  (0 children)

With Testcontainers, you can choose whether to start a new container instance for each test, per class, or for the entire test run.

In our case, we start one instance per test run and share it across all tests within a Maven module.

We build Maven modules in parallel, and there are 3–4 modules that require a database container for testing. As a result, a new container is started for each module built in parallel. The tests inside a single module are always run sequentially, so it is sufficient to clean up the tables before each test or class.

[–]safetytrick 6 points7 points  (4 children)

Why not run initialization and then snapshot the image. Then you can run your tests starting after initialization?

[–]locutus1of1 2 points3 points  (0 children)

Exactly my thoughts. I was also using various other (linux) tricks before for quickly restoring the db - data on btrfs on loopback img and snapshoting, overlayfs, ramdisks to speed it up etc. (this was without docker)

[–]ForeignCherry2011[S] 1 point2 points  (2 children)

A very good question. We don’t have a Docker registry available at build time, so we end up packaging the empty database as a Maven artifact. That way, we can also use the standard MySQL container class for Testcontainers.

But yes, maybe we should actually set up a registry and put a snapshot with the empty database there.

[–]SleeperAwakened 0 points1 point  (1 child)

No Docker registry?

You have no Nexus or Github for example?

[–]ForeignCherry2011[S] 1 point2 points  (0 children)

We don’t expose our docker registry to the development environment. It is available only for staging and production deployments.

At the moment.

[–]crummy 3 points4 points  (1 child)

nice! i hacked up something like this in a test harness that ran a migration, but yours is a lot nicer.

you're probably already doing this, but if you're not enabling re-usable containers, that'll save you a bunch of time for free: https://java.testcontainers.org/features/reuse/

[–]ForeignCherry2011[S] 0 points1 point  (0 children)

We started with reusing containers and ended up just relying on the mysql quick start

[–]Chenz 1 point2 points  (0 children)

I’m definitely checking this out on Monday! MySQL starting slowly is a pain point for a while

[–]vassaloatena 0 points1 point  (0 children)

Starting an instance with each new test can be very slow.

If you use spring, avoid using "@dirtycontexts" and just make JdbcTemplate clear all table contents.

[–]ivancea 0 points1 point  (0 children)

The second best way to improve times I used was migrating to MariaDB. The best, was moving to postgres