ebean-orm / ebean-test-containers

Ability to control docker containers. e.g. Postgres running as docker container for testing
Apache License 2.0
5 stars 2 forks source link

provide control of database cleanup during test run #108

Open macruch opened 11 months ago

macruch commented 11 months ago

using this dependency was pretty easy and worked without any hassle. Thanks for this.

expected behavior

  1. schema drop or clean up between every test class or method or the control of doing it when it suites my needs.
  2. the database is initialized with all change set applied after each other

actual behavior

  1. the database is initialized once during test run
  2. only the initial script is executed

why is this important

  1. when the database is not cleaned up between tests the, tests effects each other and I do not want to do cleanup code at the end of each test. With Micronaut framework it was recreating the database with every test class, so I had only to keep the effect in mind within one test class

  2. maybe I have added some custom migration code in one of the changesets I want that this is executed during tests. Also, using the initial script is not the behavior on the real environment, but I want to test it

workaround

  1. using plain test containers instead of ebean-test-containers
  2. using a flyway dependency cleaning up the database and appying all changesets and initial/test data

This prevents using horrible code using e.g. pg_tables to iterate over all table to truncate them and I have more control over cleanup and which data should be provided per test

Nevertheless it would ne very nice to have included this in the ebean-test-containers

rbygrave commented 3 months ago

schema drop or clean up between every test class or method

This can be slow and generally I'd say very slow - so the practicality of this approach depends on the database being used and the size and complexity of the schema. For example, this wouldn't be very practical with a database that is relatively slow to execute DDL like say Yugabyte or in the case with a decent number of tables. That is, executing DDL is often not very fast at all and ultimately its a function of subjective things like "how fast is fast" and "how many tests you want to run".

The alternative is to use table truncation before a test and imo this is what most databases want us to do technically (due to the way truncate works).

Q: Am I keen on an approach that drops and recreates the database between each test?

A: Not really. That is possibly because I want these tests to run faster than you do? and/or I want to run a lot more tests against the database than you do? (I'm a very big proponent of "Component testing" so I expect a LOT of tests to run against the test database container). I also have 7 years of experience doing this in the "using truncate way" and I also know that some databases are very slow at executing DDL - so these things bias me.

Q: But I only use Postgres and that executes DDL pretty fast. A: Yes it's pretty fast but get a bigger schema and imo recreating the database for every single test and you will start to feel that in execution time. How fast does it run, how big is your schema etc?

horrible code using e.g. pg_tables to iterate over all table to truncate them

I'd be interested to see this horrible code. You can just have a script in src/test/resources that truncates each table and it's one line for ebean to execute that script so that seems similar? To me the important note is that truncate is much nicer for most databases to execute quickly and so scales much better.

macruch commented 3 months ago

Thanks for the explanation. It's seems my database was not yet big enough causing runtime issues.

Some questions:

Thanks

rbygrave commented 3 months ago

how do you make ... is no stale data from previous test?

A lot of tests work by setting up their own data (and it doesn't matter that there is other data). Other tests use truncate.

Doing the table truncate with pg_tables?

No, I use ebean database.truncate(...) or database.script().run(...); where the script contains truncate commands.

How do you test that a change set will apply to a database

Use ddlMode: migrations

... as per application-test.yaml https://ebean.io/docs/testing/#ddlmode