I encountered an asymmetry between TestCase and TransactionTestCase regarding when fixtures are made available. I’d like to propose eliminating the potential gotcha. [ticket] [pull request]
On databases that support transactions, TestCase loads fixtures only once, during setUpClass(). This is so that each test can roll back to the end of setUpClass()/setUpTestData().
TransactionTestCase flushes after each test instead of using transactions, so there’s less of a use case for loading fixtures on a class basis on the idea that you likely also want fixture data available during the tests themselves. I figure this is why TransactionTestCase doesn’t bother to override setUpClass().
However, I had cases where during class setup I wanted to call application logic that prepares temp directories and where this logic depended on fixtures (or more precisely, data from migrations, enabled with serialized_rollback=True, but the situation is the same as with the fixtures class attribute).
By trial and error, I found that the test data I was depending on weren’t available during setUpClass() but only during setUp(). I would have discovered this faster if I was using fixtures, but I happened to be using data from initial migrations with serialized_rollback, so the situation was more deceiving: my class with a single test method passed in isolation, since flushing only happens after each test, not before, and only failed in combination with other tests in the same pattern.
I think we can improve this situation:
- The docs don’t caution that fixture data are only available in certain parts of the test lifecycle.
- I think there’s a use case for depending on initial data in class setup even if
TransactionTestCasewill flush between tests, e.g. to perform side effects. - The
serialized_rollbackcase is deceiving, causing difficult to debug failures when tests are combined after the fact.
Do folks agree this asymmetry is worth addressing?