Description

The Django TransactionTestCase fails to roll back the current database transaction at each test's conclusion, which can leave the current database connection in an unusable state and thus break test isolation. When Django is using PostgreSQL, and a test deliberately tries violating a database invariant (like inserting an illegal value, or a non-existent primary key) and receives a PostgreSQL runtime error, then all subsequent tests in that test class error out with the failure:

The correction for this is very simple: the _fixture_teardown() method in django.test.testcases.TransactionTestCase needs its code changed from a do-nothing "pass" statement to something more effective:

def _fixture_teardown(self):
transaction.rollback()

With this small change, test isolation is correctly achieved, and the rest of the test cases in the TransactionTestCase class can succeed and fail on their own rather than all dying with the error shown above.

To my eyes, TransactionTestCase does exactly what ​the documentation says it does: force you to handle transactions yourself. This means that you need to do the commit/rollback handling yourself.

Remember you can always easily writing your own TestCase (or TransactionTestCase subclass to handle this stuff however your app wants. Django provides two common options; less common ones can -- and should -- be confined to your own projects.

[Yes, TransactionTestCase could have been named better. Water under the bridge now, though.]