﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
20142	Transaction methods are not re-enabled when fixture loading fails	Martin Larente	Filipa Andrade	"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."	Bug	closed	Testing framework	1.5	Normal	fixed			Accepted	1	0	0	0	1	0
