#20142: Transaction methods are not re-enabled when fixture loading fails
-----------------------------------+--------------------
Reporter: mlarente | Owner: nobody
Type: Bug | Status: new
Component: Testing framework | Version: 1.5
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
-----------------------------------+--------------------
When a test case fails to properly load a fixture (integrity error or some
other reason), the transaction methods (which are disabled before the test
is run) are not re-enabled before the next test is run. This can cause
other tests (especially transaction test cases) to fail.
I've created a simple django application to reproduce this. You just have
to add the application to a Django project, and then run:
{{{
manage.py test myapp.Before myapp.Broken myapp.After
}}}
This command is used to enforce the test order that shows the bug. The
`Before` and `After` tests are actually the same test that checks if
transaction methods are enabled (as they should be for a transaction test
case). The first one passes and the other one fails:
{{{
import django.db.transaction
from django.test.testcases import TestCase
from django.test.testcases import TransactionTestCase
ORIGINAL = django.db.transaction.enter_transaction_management
class TransactionCheckMixin(object):
def test_transaction_method(self):
self.assertEqual(ORIGINAL,
django.db.transaction.enter_transaction_management)
class Before(TransactionCheckMixin, TransactionTestCase):
pass
class Broken(TestCase):
fixtures = ['broken_fixture']
def test_something(self):
self.assertTrue(True) # will not happen
class After(TransactionCheckMixin, TransactionTestCase):
pass
}}}
The problem lies in the `_fixture_setup` method of the `TestCase` class:
{{{
class TestCase(TransactionTestCase):
"""
Does basically the same as TransactionTestCase, but surrounds every
test
with a transaction, monkey-patches the real transaction management
routines
to do nothing, and rollsback the test transaction at the end of the
test.
You have to use TransactionTestCase, if you need transaction
management
inside a test.
"""
def _fixture_setup(self):
if not connections_support_transactions():
return super(TestCase, self)._fixture_setup()
assert not self.reset_sequences, 'reset_sequences cannot be used
on TestCase instances'
for db_name in self._databases_names():
transaction.enter_transaction_management(using=db_name)
transaction.managed(True, using=db_name)
disable_transaction_methods()
from django.contrib.sites.models import Site
Site.objects.clear_cache()
for db in self._databases_names(include_mirrors=False):
if hasattr(self, 'fixtures'):
call_command('loaddata', *self.fixtures,
**{
'verbosity': 0,
'commit': False,
'database': db,
'skip_validation': True,
})
}}}
It should handle errors and call the `_fixture_teardown` method if there's
an error.
--
Ticket URL: <https://code.djangoproject.com/ticket/20142>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.