Commit 00276e04 authored by Andrew Godwin's avatar Andrew Godwin
Browse files

Add tests for the migrate command and fix a bug they exposed

parent 162f7b93
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ class Command(BaseCommand):
            if app_label not in executor.loader.migrated_apps:
                raise CommandError("App '%s' does not have migrations (you cannot selectively sync unmigrated apps)" % app_label)
            if migration_name == "zero":
                migration_name = None
                targets = [(app_label, None)]
            else:
                try:
                    migration = executor.loader.get_migration_by_prefix(app_label, migration_name)
@@ -110,6 +110,7 @@ class Command(BaseCommand):
        # Run the syncdb phase.
        # If you ever manage to get rid of this, I owe you many, many drinks.
        if run_syncdb:
            if self.verbosity >= 1:
                self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:"))
            self.sync_apps(connection, executor.loader.unmigrated_apps)

+39 −0
Original line number Diff line number Diff line
from django.test import TestCase
from django.db import connection


class MigrationTestBase(TestCase):
    """
    Contains an extended set of asserts for testing migrations and schema operations.
    """

    def assertTableExists(self, table):
        self.assertIn(table, connection.introspection.get_table_list(connection.cursor()))

    def assertTableNotExists(self, table):
        self.assertNotIn(table, connection.introspection.get_table_list(connection.cursor()))

    def assertColumnExists(self, table, column):
        self.assertIn(column, [c.name for c in connection.introspection.get_table_description(connection.cursor(), table)])

    def assertColumnNotExists(self, table, column):
        self.assertNotIn(column, [c.name for c in connection.introspection.get_table_description(connection.cursor(), table)])

    def assertColumnNull(self, table, column):
        self.assertEqual([c.null_ok for c in connection.introspection.get_table_description(connection.cursor(), table) if c.name == column][0], True)

    def assertColumnNotNull(self, table, column):
        self.assertEqual([c.null_ok for c in connection.introspection.get_table_description(connection.cursor(), table) if c.name == column][0], False)

    def assertIndexExists(self, table, columns, value=True):
        self.assertEqual(
            value,
            any(
                c["index"]
                for c in connection.introspection.get_constraints(connection.cursor(), table).values()
                if c['columns'] == list(columns)
            ),
        )

    def assertIndexNotExists(self, table, columns):
        return self.assertIndexExists(table, columns, False)
+37 −0
Original line number Diff line number Diff line
from django.core.management import call_command
from django.test.utils import override_settings
from .test_base import MigrationTestBase


class CommandTests(MigrationTestBase):
    """
    Tests running the commands (migrate, makemigrations).
    """

    @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
    def test_migrate(self):
        """
        Tests basic usage of the migrate command.
        """
        # Make sure no tables are created
        self.assertTableNotExists("migrations_author")
        self.assertTableNotExists("migrations_tribble")
        self.assertTableNotExists("migrations_book")
        # Run the migrations to 0001 only
        call_command("migrate", "migrations", "0001", verbosity=0)
        # Make sure the right tables exist
        self.assertTableExists("migrations_author")
        self.assertTableExists("migrations_tribble")
        self.assertTableNotExists("migrations_book")
        # Run migrations all the way
        call_command("migrate", verbosity=0)
        # Make sure the right tables exist
        self.assertTableExists("migrations_author")
        self.assertTableNotExists("migrations_tribble")
        self.assertTableExists("migrations_book")
        # Unmigrate everything
        call_command("migrate", "migrations", "zero", verbosity=0)
        # Make sure it's all gone
        self.assertTableNotExists("migrations_author")
        self.assertTableNotExists("migrations_tribble")
        self.assertTableNotExists("migrations_book")
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ class ExecutorTests(TransactionTestCase):
        Tests running a simple set of migrations.
        """
        executor = MigrationExecutor(connection)
        executor.recorder.flush()
        # Let's look at the plan first and make sure it's up to scratch
        plan = executor.migration_plan([("migrations", "0002_second")])
        self.assertEqual(
+1 −1
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ class Migration(migrations.Migration):
                ("name", models.CharField(max_length=255)),
                ("slug", models.SlugField(null=True)),
                ("age", models.IntegerField(default=0)),
                ("silly_field", models.BooleanField()),
                ("silly_field", models.BooleanField(default=False)),
            ],
        ),

Loading