Commit f758bdab authored by Ramiro Morales's avatar Ramiro Morales
Browse files

Fixed #18271 -- Changed stage at which TransactionTestCase flushes DB tables.

Previously, the flush was done before the test case execution and now
it is performed after it.

Other changes to the testing infrastructure include:

* TransactionTestCase now doesn't reset autoincrement sequences either
  (previous behavior can achieved by using `reset_sequences`.)
  With this, no implicit such reset is performed by any of the provided
  TestCase classes.

* New ordering of test cases: All unittest tes cases are run first and
  doctests are run at the end.

THse changes could be backward-incompatible with test cases that relied
on some kind of state being preserved between tests. Please read the
relevant sections of the release notes and testing documentation for
further details.

Thanks Andreas Pelme for the initial patch. Karen Tracey and Anssi
Kääriäinen for the feedback and Anssi for reviewing.

This also fixes #12408.
parent 38ce709f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ class Command(NoArgsCommand):
        connection = connections[db]
        verbosity = int(options.get('verbosity'))
        interactive = options.get('interactive')
        # 'reset_sequences' is a stealth option
        reset_sequences = options.get('reset_sequences', True)

        self.style = no_style()

@@ -40,7 +42,7 @@ class Command(NoArgsCommand):
            except ImportError:
                pass

        sql_list = sql_flush(self.style, connection, only_django=True)
        sql_list = sql_flush(self.style, connection, only_django=True, reset_sequences=reset_sequences)

        if interactive:
            confirm = raw_input("""You have requested a flush of the database.
+3 −4
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ def sql_delete(app, style, connection):

    return output[::-1] # Reverse it, to deal with table dependencies.

def sql_flush(style, connection, only_django=False):
def sql_flush(style, connection, only_django=False, reset_sequences=True):
    """
    Returns a list of the SQL statements used to flush the database.

@@ -109,9 +109,8 @@ def sql_flush(style, connection, only_django=False):
        tables = connection.introspection.django_table_names(only_existing=True)
    else:
        tables = connection.introspection.table_names()
    statements = connection.ops.sql_flush(
        style, tables, connection.introspection.sequence_list()
    )
    seqs = connection.introspection.sequence_list() if reset_sequences else ()
    statements = connection.ops.sql_flush(style, tables, seqs)
    return statements

def sql_custom(app, style, connection):
+13 −0
Original line number Diff line number Diff line
@@ -748,11 +748,24 @@ class BaseDatabaseOperations(object):
        the given database tables (without actually removing the tables
        themselves).

        The returned value also includes SQL statements required to reset DB
        sequences passed in :param sequences:.

        The `style` argument is a Style object as returned by either
        color_style() or no_style() in django.core.management.color.
        """
        raise NotImplementedError()

    def sequence_reset_by_name_sql(self, style, sequences):
        """
        Returns a list of the SQL statements required to reset sequences
        passed in :param sequences:.

        The `style` argument is a Style object as returned by either
        color_style() or no_style() in django.core.management.color.
        """
        return []

    def sequence_reset_sql(self, style, model_list):
        """
        Returns a list of the SQL statements required to reset sequences for
+15 −12
Original line number Diff line number Diff line
@@ -262,19 +262,22 @@ class DatabaseOperations(BaseDatabaseOperations):
            for table in tables:
                sql.append('%s %s;' % (style.SQL_KEYWORD('TRUNCATE'), style.SQL_FIELD(self.quote_name(table))))
            sql.append('SET FOREIGN_KEY_CHECKS = 1;')
            sql.extend(self.sequence_reset_by_name_sql(style, sequences))
            return sql
        else:
            return []

    def sequence_reset_by_name_sql(self, style, sequences):
        # Truncate already resets the AUTO_INCREMENT field from
        # MySQL version 5.0.13 onwards. Refs #16961.
        if self.connection.mysql_version < (5, 0, 13):
                sql.extend(
                    ["%s %s %s %s %s;" % \
            return ["%s %s %s %s %s;" % \
                    (style.SQL_KEYWORD('ALTER'),
                    style.SQL_KEYWORD('TABLE'),
                    style.SQL_TABLE(self.quote_name(sequence['table'])),
                    style.SQL_KEYWORD('AUTO_INCREMENT'),
                    style.SQL_FIELD('= 1'),
                     ) for sequence in sequences])
            return sql
                    ) for sequence in sequences]
        else:
            return []

+13 −8
Original line number Diff line number Diff line
@@ -298,6 +298,13 @@ WHEN (new.%(col_name)s IS NULL)
                    for table in tables]
            # Since we've just deleted all the rows, running our sequence
            # ALTER code will reset the sequence to 0.
            sql.extend(self.sequence_reset_by_name_sql(style, sequences))
            return sql
        else:
            return []

    def sequence_reset_by_name_sql(self, style, sequences):
        sql = []
        for sequence_info in sequences:
            sequence_name = self._get_sequence_name(sequence_info['table'])
            table_name = self.quote_name(sequence_info['table'])
@@ -307,8 +314,6 @@ WHEN (new.%(col_name)s IS NULL)
                                                    'column': column_name}
            sql.append(query)
        return sql
        else:
            return []

    def sequence_reset_sql(self, style, model_list):
        from django.db import models
Loading