What are the generic patterns and best practices for resetting state of a database, storage, external service, etc, in Acceptance Tests?
I'm struggling with spaghetti, living in acceptance tests. It connects to the remote DB, executes SQL, Rebuilds buckets through AWS S3 API, reaches into a payment provider API to delete payments and so on. It does this between every scenario, so the tests are isolated.
This is specific for acceptance tests, that test the integration of a service as a whole and the data flow between some services (integration of multiple services). There is hexagonal service, which has an HTTP API, HTML UI, CLI UI on one side and some services like a database, file-storage, payment service, SMTP, push notification etc on the other side. Many of these services need to be reset, as they affect the state of the app and thus how acceptance tests can run.
My current strategy makes the acceptance tests tightly coupled to implementation details which, as far as I know, the tests should best be unaware of.
But it also introduces practical difficulties, for example, I now need to open the database server to allow connections (which can delete data, schema's etc) from "random" test runners "anywhere" on the web (I'm using Github Actions, but the same would apply to AWS pipelines or CircleCI or most hosted test-runners). So this also has security implications, makes it hard to migrate and so on.
Strategies I'm considering are:
- Ensure the acceptance tests use unique (random) names and attrs . No need to reset.
- Move the reset-logic into the app into a public "reset interface".
- Keep reset-logic in the accptance tests but refactor them to be less spaghetti. Deal with the practical problems with e.g. VPN or proxies.
Yet I'm certain more people have this problem. And certain that is has been solved multiple times already. So I'm mostly looking for any hints, talks, articles, or books that explain solutions and their tradeoffs.