Ticket #8138: django_transaction_tests_2.diff

File django_transaction_tests_2.diff, 7.5 KB (added by lukeplant, 7 years ago)
  • django/core/management/commands/loaddata.py

    diff -r ed4d2e6277b2 django/core/management/commands/loaddata.py
    a b  
    2828
    2929        verbosity = int(options.get('verbosity', 1))
    3030        show_traceback = options.get('traceback', False)
     31        no_commit = options.get('no_commit', False)
    3132
    3233        # Keep a count of the installed objects and fixtures
    3334        fixture_count = 0
     
    4445
    4546        # Start transaction management. All fixtures are installed in a
    4647        # single transaction to ensure that all references are resolved.
    47         transaction.commit_unless_managed()
    48         transaction.enter_transaction_management()
    49         transaction.managed(True)
     48        if not no_commit:
     49            transaction.commit_unless_managed()
     50            transaction.enter_transaction_management()
     51            transaction.managed(True)
    5052
    5153        app_fixtures = [os.path.join(os.path.dirname(app.__file__), 'fixtures') for app in get_apps()]
    5254        for fixture_label in fixture_labels:
     
    133135                                (format, fixture_name, humanize(fixture_dir))
    134136
    135137
    136         # If any of the fixtures we loaded contain 0 objects, assume that an 
     138        # If any of the fixtures we loaded contain 0 objects, assume that an
    137139        # error was encountered during fixture loading.
    138140        if 0 in objects_per_fixture:
    139141            sys.stderr.write(
     
    142144            transaction.rollback()
    143145            transaction.leave_transaction_management()
    144146            return
    145            
    146         # If we found even one object in a fixture, we need to reset the 
     147
     148        # If we found even one object in a fixture, we need to reset the
    147149        # database sequences.
    148150        if object_count > 0:
    149151            sequence_sql = connection.ops.sequence_reset_sql(self.style, models)
     
    152154                    print "Resetting sequences"
    153155                for line in sequence_sql:
    154156                    cursor.execute(line)
    155            
    156         transaction.commit()
    157         transaction.leave_transaction_management()
     157
     158        if not no_commit:
     159            transaction.commit()
     160            transaction.leave_transaction_management()
    158161
    159162        if object_count == 0:
    160163            if verbosity > 1:
     
    162165        else:
    163166            if verbosity > 0:
    164167                print "Installed %d object(s) from %d fixture(s)" % (object_count, fixture_count)
    165                
     168
    166169        # Close the DB connection. This is required as a workaround for an
    167170        # edge case in MySQL: if the same connection is used to
    168171        # create tables, load data, and query, the query can return
    169172        # incorrect results. See Django #7572, MySQL #37735.
    170         connection.close()
     173        if not no_commit:
     174            connection.close()
  • django/test/__init__.py

    diff -r ed4d2e6277b2 django/test/__init__.py
    a b  
    33"""
    44
    55from django.test.client import Client
    6 from django.test.testcases import TestCase
     6from django.test.testcases import TestCase, TransactionTestCase
  • django/test/testcases.py

    diff -r ed4d2e6277b2 django/test/testcases.py
    a b  
    5555        """Tries to do a 'xml-comparision' of want and got.  Plain string
    5656        comparision doesn't always work because, for example, attribute
    5757        ordering should not be important.
    58        
     58
    5959        Based on http://codespeak.net/svn/lxml/trunk/src/lxml/doctestcompare.py
    6060        """
    6161        _norm_whitespace_re = re.compile(r'[ \t\n][ \t\n]+')
     
    102102            wrapper = '<root>%s</root>'
    103103            want = wrapper % want
    104104            got = wrapper % got
    105            
     105
    106106        # Parse the want and got strings, and compare the parsings.
    107107        try:
    108108            want_root = parseString(want).firstChild
     
    169169        # side effects on other tests.
    170170        transaction.rollback_unless_managed()
    171171
    172 class TestCase(unittest.TestCase):
     172    def run(self, test, compileflags=None, out=None, clear_globs=True):
     173        """
     174        Wraps the parent run() and encloses it in a transaction.
     175        """
     176        transaction.enter_transaction_management()
     177        transaction.managed(True)
     178        result = doctest.DocTestRunner.run(self, test, compileflags, out, clear_globs)
     179        transaction.rollback()
     180        transaction.leave_transaction_management()
     181        return result
     182
     183class TransactionTestCase(unittest.TestCase):
    173184    def _pre_setup(self):
    174185        """Performs any pre-test setup. This includes:
    175186
    176187            * Flushing the database.
    177             * If the Test Case class has a 'fixtures' member, installing the 
     188            * If the Test Case class has a 'fixtures' member, installing the
    178189              named fixtures.
    179190            * If the Test Case class has a 'urls' member, replace the
    180191              ROOT_URLCONF with it.
    181192            * Clearing the mail test outbox.
    182193        """
     194        self._fixture_setup()
     195        self._urlconf_setup()
     196        mail.outbox = []
     197
     198    def _fixture_setup(self):
    183199        call_command('flush', verbosity=0, interactive=False)
    184200        if hasattr(self, 'fixtures'):
    185201            # We have to use this slightly awkward syntax due to the fact
    186202            # that we're using *args and **kwargs together.
    187203            call_command('loaddata', *self.fixtures, **{'verbosity': 0})
     204
     205    def _urlconf_setup(self):
    188206        if hasattr(self, 'urls'):
    189207            self._old_root_urlconf = settings.ROOT_URLCONF
    190208            settings.ROOT_URLCONF = self.urls
    191209            clear_url_caches()
    192         mail.outbox = []
    193210
    194211    def __call__(self, result=None):
    195212        """
     
    206223            import sys
    207224            result.addError(self, sys.exc_info())
    208225            return
    209         super(TestCase, self).__call__(result)
     226        super(TransactionTestCase, self).__call__(result)
    210227        try:
    211228            self._post_teardown()
    212229        except (KeyboardInterrupt, SystemExit):
     
    221238
    222239            * Putting back the original ROOT_URLCONF if it was changed.
    223240        """
     241        self._fixture_teardown()
     242        self._urlconf_teardown()
     243
     244    def _fixture_teardown(self):
     245        pass
     246
     247    def _urlconf_teardown(self):
    224248        if hasattr(self, '_old_root_urlconf'):
    225249            settings.ROOT_URLCONF = self._old_root_urlconf
    226250            clear_url_caches()
     
    354378        self.failIf(template_name in template_names,
    355379            (u"Template '%s' was used unexpectedly in rendering the"
    356380             u" response") % template_name)
     381
     382class TestCase(TransactionTestCase):
     383    """
     384    Does basically the same as TransactionTestCase, but surrounds every test
     385    with a transaction. You have to use TransactionTestCase, if you need
     386    transaction management inside a test.
     387    """
     388    def _fixture_setup(self):
     389        transaction.enter_transaction_management()
     390        transaction.managed(True)
     391
     392        if hasattr(self, 'fixtures'):
     393            call_command('loaddata', *self.fixtures, **{
     394                                                        'verbosity': 0,
     395                                                        'no_commit': True
     396                                                        })
     397
     398    def _fixture_teardown(self):
     399        transaction.rollback()
     400        transaction.leave_transaction_management()
Back to Top