I faced problems with flaky unit tests that used a common unit test database for the whole project. Since all the tests ran at once, the tests would sometimes fail because of concurrency issues. I never got the time to look too deeply into it.
I wonder if there's a database that works sorta like git, giving one "commit" point at the start of every test and then "branching off" so each test can do its own thing, make transactions, commit them, whatever, and finally be able to roll the whole thing back.
If that can be done then each unit test can use a full database clone with actual valid data and not just test data that was fast enough to set up before the test ran.
Yes, with Postgres at least you can do this by using a "template" database — run your migrations on it, then create new databases from that template. It's a very fast operation. For more information, read the Postgres docs:
Dupe the database. That's what I do in one of my test suites (though that's in part because the tests happen across 4 different processes so it's just not possible to keep it within one transaction).
Creating a db from a template is not free, but if there's not too much stuff in the db it's not horrendous either. And if you're using sqlite, you might be able to backup an on-disk template to an in-memory test db.
Starting each test in its own transaction and then rolling back at the end, and ensuring no 3rd party network calls in application logic in rails and Postgres apps have worked with a lot of success in my experience.
Transaction per test is how that works in ruby on rails. Also, the rspec parallel gem will create N test databases for running tests - one per process.
That doesn't work if you need to commit for one reason or an other. And while in some cases you might be able to substitute subtransactions via some sort of test mode, it's not always an option depending what you're doing / testing exactly.
Nested transactions handle commits. At the beginning of a test, a new transaction is begun, and it is rolled back at the end of the test. As others have pointed out in this discussion, it's pretty standard with Ruby on Rails apps, especially those which use rspec for testing.
I wonder if there's a database that works sorta like git, giving one "commit" point at the start of every test and then "branching off" so each test can do its own thing, make transactions, commit them, whatever, and finally be able to roll the whole thing back.
If that can be done then each unit test can use a full database clone with actual valid data and not just test data that was fast enough to set up before the test ran.