Hamish Downer
Hamish Downer

Reputation: 17087

TransactionManagementError while running tests, but can't find atomic block

I've hit an issue with running tests where I'm getting TransactionManagementError as soon as I start running tests. I've tried various different tests and they all hit this error:

.ve/lib/python2.7/site-packages/django/test/testcases.py:189: in __call__
    self._post_teardown()
.ve/lib/python2.7/site-packages/cms/test_utils/testcases.py:97: in _post_teardown
    menu_pool.clear()
.ve/lib/python2.7/site-packages/menus/menu_pool.py:156: in clear
    if to_be_deleted:
.ve/lib/python2.7/site-packages/django/db/models/query.py:145: in __nonzero__
    self._fetch_all()
.ve/lib/python2.7/site-packages/django/db/models/query.py:966: in _fetch_all
    self._result_cache = list(self.iterator())
.ve/lib/python2.7/site-packages/django/db/models/query.py:1202: in iterator
    for row in self.query.get_compiler(self.db).results_iter():
.ve/lib/python2.7/site-packages/django/db/models/sql/compiler.py:701: in results_iter
    for rows in self.execute_sql(MULTI):
.ve/lib/python2.7/site-packages/django/db/models/sql/compiler.py:787: in execute_sql
    cursor.execute(sql, params)
.ve/lib/python2.7/site-packages/django/db/backends/utils.py:59: in execute
    self.db.validate_no_broken_transaction()
.ve/lib/python2.7/site-packages/django/db/backends/__init__.py:386: in validate_no_broken_transaction
    "An error occurred in the current transaction. You can't "
E   TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

You can see the stack trace is in the _post_teardown method, so I guess the problem is somewhere before this test. I've looked at the code on each line of the stack trace and can't see a transaction being started in those bits of the code, so it must happen before here, but how do I find out where?

Given it happens whether I test app A alone or app B alone I'm not sure how to track down the code in question. Any suggestions welcome.

I am using Django 1.7, Django CMS 3.1 (which contains the menus app in the stack trace above) and pytest as the test runner. I am for this test using the --create-db argument to ensure the database is recreated cleanly.

Upvotes: 3

Views: 1615

Answers (1)

Hamish Downer
Hamish Downer

Reputation: 17087

I tracked down the change by rolling back commits until the tests passed and comparing what changed. It turned out that it was adding a post save signal handler to auto-create a linked model that was the change that stopped tests passing. I have a User model, and a UserProfile model with a OneToOneField pointing at the User model.

The problem was that the tests were often manually creating the UserProfile. Once the post_save handler was added, that would lead to an error of duplicate id for the manually created UserProfile, as the automatically created UserProfile has already used that id. I guess that caused the transaction around the unit test to fail badly, leading to all the other errors.

But that original error was hidden in the noise of the many errors about transactions.

Upvotes: 4

Related Questions