summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2013-07-25 13:52:35 +0100
committerAndrew Godwin <andrew@aeracode.org>2013-07-25 13:52:35 +0100
commit00276e0414ce796a71a28d4c675a22b041aa3450 (patch)
tree0725eefc6cdf5adfa51cfdca16feb890e3ec758c
parent162f7b938f6cff91b1e4d6086ddcc88cbb1a1cd6 (diff)
Add tests for the migrate command and fix a bug they exposed
-rw-r--r--django/core/management/commands/migrate.py7
-rw-r--r--tests/migrations/test_base.py39
-rw-r--r--tests/migrations/test_commands.py37
-rw-r--r--tests/migrations/test_executor.py1
-rw-r--r--tests/migrations/test_migrations/0001_initial.py2
-rw-r--r--tests/migrations/test_operations.py35
6 files changed, 84 insertions, 37 deletions
diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py
index 29b8b2c9c0..8e3c79a431 100644
--- a/django/core/management/commands/migrate.py
+++ b/django/core/management/commands/migrate.py
@@ -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)
@@ -81,7 +81,7 @@ class Command(BaseCommand):
raise CommandError("More than one migration matches '%s' in app '%s'. Please be more specific." % (app_label, migration_name))
except KeyError:
raise CommandError("Cannot find a migration matching '%s' from app '%s'. Is it in INSTALLED_APPS?" % (app_label, migration_name))
- targets = [(app_label, migration.name)]
+ targets = [(app_label, migration.name)]
target_app_labels_only = False
elif len(args) == 1:
app_label = args[0]
@@ -110,7 +110,8 @@ 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:
- self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:"))
+ if self.verbosity >= 1:
+ self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:"))
self.sync_apps(connection, executor.loader.unmigrated_apps)
# Migrate!
diff --git a/tests/migrations/test_base.py b/tests/migrations/test_base.py
new file mode 100644
index 0000000000..01062667aa
--- /dev/null
+++ b/tests/migrations/test_base.py
@@ -0,0 +1,39 @@
+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)
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
new file mode 100644
index 0000000000..d775d1eba7
--- /dev/null
+++ b/tests/migrations/test_commands.py
@@ -0,0 +1,37 @@
+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")
diff --git a/tests/migrations/test_executor.py b/tests/migrations/test_executor.py
index c426defe4a..ddbfa78db7 100644
--- a/tests/migrations/test_executor.py
+++ b/tests/migrations/test_executor.py
@@ -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(
diff --git a/tests/migrations/test_migrations/0001_initial.py b/tests/migrations/test_migrations/0001_initial.py
index e2ed8559a6..f20bac8aec 100644
--- a/tests/migrations/test_migrations/0001_initial.py
+++ b/tests/migrations/test_migrations/0001_initial.py
@@ -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)),
],
),
diff --git a/tests/migrations/test_operations.py b/tests/migrations/test_operations.py
index 810ed0b929..c74d40e4f2 100644
--- a/tests/migrations/test_operations.py
+++ b/tests/migrations/test_operations.py
@@ -1,48 +1,17 @@
-from django.test import TestCase
from django.db import connection, models, migrations
from django.db.transaction import atomic
from django.db.utils import IntegrityError
from django.db.migrations.state import ProjectState
+from .test_base import MigrationTestBase
-class OperationTests(TestCase):
+class OperationTests(MigrationTestBase):
"""
Tests running the operations and making sure they do what they say they do.
Each test looks at their state changing, and then their database operation -
both forwards and backwards.
"""
- 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)
-
def set_up_test_model(self, app_label):
"""
Creates a test model state and database table.