If you’re running automated functional testing as part of your build process, you probably know about test isolation (Martin Fowler has a great article on this and other issues with test non-determinism):
For test isolation, you need a clean application state between tests. This can be accomplished in several ways, and depends on your problem domain. For example, if your application is multi-tenant, you could have each test create a new tenant. A tenant could be something as simple as a user.
We approached our automated functional testing in a slightly different way: resetting the entire database between tests. But first, a little background:
As we began writing our Geb tests, we had a cleanup section in each test to reverse changes we had made: delete records, un-update records, etc. However, this quickly ballooned out of control as it was impossible to know in advance where a test would fail, so we had to build a complicated set of logic in the cleanup block of each test (delete record, but only if it exists). The tests were difficult to maintain and that was a problem.
As we were running against an H2 database, it was quite simple to reset the database between tests. (We did not use Spring’s @Transactional on integration tests because we wanted our tests to run against an application server, not just a Spring application context.)
Step 1: Configure H2 to save to a local file
This saves the database to a location in the file system, and utilizes an H2 feature that allows multiple processes to connect to the same database.
Step 2: Backup and reload database before and after tests
We created a Groovy trait with Spock setup and cleanup methods. If your tests are not all in Spock, or you can’t use Groovy 2.3 traits, you could try some other method for code-reuse, such as static methods or test class inheritance.
And that’s it! Your functional tests will all start with an environment in the same state, regardless of how the previous test ended up. I’ve created a Github repo using Spring Boot, if you’re looking for a fleshed-out example.