summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorMarkus Holtermann <info@markusholtermann.eu>2014-11-17 23:09:08 +0100
committerTim Graham <timograham@gmail.com>2014-11-19 18:25:00 -0500
commit1b8c067a4f7b022dabe4e0a068bc0836e46c822b (patch)
tree177d7b0c0f6775ab20af93edc482bbb92ce05d33 /tests
parent2f8cd09a0654befa77dee3b32bbf82e231ff9e62 (diff)
[1.7.x] Cleaned up and reformatted autodetector tests
Backport of 233165083593baf5f62194f50df26fb830e5f570 from master.
Diffstat (limited to 'tests')
-rw-r--r--tests/migrations/test_autodetector.py949
1 files changed, 475 insertions, 474 deletions
diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py
index 9e895fccd5..1cf0598c85 100644
--- a/tests/migrations/test_autodetector.py
+++ b/tests/migrations/test_autodetector.py
@@ -256,7 +256,7 @@ class AutodetectorTests(TestCase):
("parent", models.ForeignKey("eggs.Rabbit")),
], {"unique_together": {("parent", "knight")}})
- def repr_changes(self, changes):
+ def repr_changes(self, changes, include_dependencies=False):
output = ""
for app_label, migrations in sorted(changes.items()):
output += " %s:\n" % app_label
@@ -264,6 +264,13 @@ class AutodetectorTests(TestCase):
output += " %s\n" % migration.name
for operation in migration.operations:
output += " %s\n" % operation
+ if include_dependencies:
+ output += " Dependencies:\n"
+ if migration.dependencies:
+ for dep in migration.dependencies:
+ output += " %s\n" % (dep,)
+ else:
+ output += " None\n"
return output
def assertNumberMigrations(self, changes, app_label, number):
@@ -275,8 +282,22 @@ class AutodetectorTests(TestCase):
self.repr_changes(changes),
))
+ def assertMigrationDependencies(self, changes, app_label, index, dependencies):
+ if not changes.get(app_label):
+ self.fail("No migrations found for %s\n%s" % (app_label, self.repr_changes(changes)))
+ if len(changes[app_label]) < index + 1:
+ self.fail("No migration at index %s for %s\n%s" % (index, app_label, self.repr_changes(changes)))
+ migration = changes[app_label][index]
+ if set(migration.dependencies) != set(dependencies):
+ self.fail("Migration dependencies mismatch for %s.%s (expected %s):\n%s" % (
+ app_label,
+ migration.name,
+ dependencies,
+ self.repr_changes(changes, include_dependencies=True),
+ ))
+
def assertOperationTypes(self, changes, app_label, index, types):
- if not changes.get(app_label, None):
+ if not changes.get(app_label):
self.fail("No migrations found for %s\n%s" % (app_label, self.repr_changes(changes)))
if len(changes[app_label]) < index + 1:
self.fail("No migration at index %s for %s\n%s" % (index, app_label, self.repr_changes(changes)))
@@ -291,7 +312,7 @@ class AutodetectorTests(TestCase):
))
def assertOperationAttributes(self, changes, app_label, index, operation_index, **attrs):
- if not changes.get(app_label, None):
+ if not changes.get(app_label):
self.fail("No migrations found for %s\n%s" % (app_label, self.repr_changes(changes)))
if len(changes[app_label]) < index + 1:
self.fail("No migration at index %s for %s\n%s" % (index, app_label, self.repr_changes(changes)))
@@ -316,6 +337,39 @@ class AutodetectorTests(TestCase):
self.repr_changes(changes),
))
+ def assertOperationFieldAttributes(self, changes, app_label, index, operation_index, **attrs):
+ if not changes.get(app_label):
+ self.fail("No migrations found for %s\n%s" % (app_label, self.repr_changes(changes)))
+ if len(changes[app_label]) < index + 1:
+ self.fail("No migration at index %s for %s\n%s" % (index, app_label, self.repr_changes(changes)))
+ migration = changes[app_label][index]
+ if len(changes[app_label]) < index + 1:
+ self.fail("No operation at index %s for %s.%s\n%s" % (
+ operation_index,
+ app_label,
+ migration.name,
+ self.repr_changes(changes),
+ ))
+ operation = migration.operations[operation_index]
+ if not hasattr(operation, 'field'):
+ self.fail("No field attribute for %s.%s op #%s." % (
+ app_label,
+ migration.name,
+ operation_index,
+ ))
+ field = operation.field
+ for attr, value in attrs.items():
+ if getattr(field, attr, None) != value:
+ self.fail("Field attribute mismatch for %s.%s op #%s, field.%s (expected %r, got %r):\n%s" % (
+ app_label,
+ migration.name,
+ operation_index,
+ attr,
+ value,
+ getattr(field, attr, None),
+ self.repr_changes(changes),
+ ))
+
def make_project_state(self, model_states):
"Shortcut to make ProjectStates from lists of predefined models"
project_state = ProjectState()
@@ -324,7 +378,7 @@ class AutodetectorTests(TestCase):
return project_state
def test_arrange_for_graph(self):
- "Tests auto-naming of migrations for graph matching."
+ """Tests auto-naming of migrations for graph matching."""
# Make a fake graph
graph = MigrationGraph()
graph.add_node(("testapp", "0001_initial"), None)
@@ -346,7 +400,10 @@ class AutodetectorTests(TestCase):
self.assertEqual(changes["otherapp"][0].dependencies, [("otherapp", "0001_initial")])
def test_trim_apps(self):
- "Tests that trim does not remove dependencies but does remove unwanted apps"
+ """
+ Tests that trim does not remove dependencies but does remove unwanted
+ apps.
+ """
# Use project state to make a new migration change set
before = self.make_project_state([])
after = self.make_project_state([self.author_empty, self.other_pony, self.other_stable, self.third_thing])
@@ -363,93 +420,69 @@ class AutodetectorTests(TestCase):
self.assertNotIn("thirdapp", changes)
def test_new_model(self):
- "Tests autodetection of new models"
+ """Tests autodetection of new models."""
# Make state
before = self.make_project_state([])
after = self.make_project_state([self.author_empty])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "CreateModel")
- self.assertEqual(action.name, "Author")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
def test_old_model(self):
- "Tests deletion of old models"
+ """Tests deletion of old models."""
# Make state
before = self.make_project_state([self.author_empty])
after = self.make_project_state([])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "DeleteModel")
- self.assertEqual(action.name, "Author")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["DeleteModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
def test_add_field(self):
- "Tests autodetection of new fields"
+ """Tests autodetection of new fields."""
# Make state
before = self.make_project_state([self.author_empty])
after = self.make_project_state([self.author_name])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AddField")
- self.assertEqual(action.name, "name")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="name")
def test_remove_field(self):
- "Tests autodetection of removed fields"
+ """Tests autodetection of removed fields."""
# Make state
before = self.make_project_state([self.author_name])
after = self.make_project_state([self.author_empty])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "RemoveField")
- self.assertEqual(action.name, "name")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["RemoveField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="name")
def test_alter_field(self):
- "Tests autodetection of new fields"
+ """Tests autodetection of new fields."""
# Make state
before = self.make_project_state([self.author_name])
after = self.make_project_state([self.author_name_longer])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AlterField")
- self.assertEqual(action.name, "name")
- self.assertTrue(action.preserve_default)
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=True)
def test_alter_field_to_not_null_with_default(self):
- "#23609 - Tests autodetection of nullable to non-nullable alterations"
+ """
+ #23609 - Tests autodetection of nullable to non-nullable alterations.
+ """
class CustomQuestioner(MigrationQuestioner):
def ask_not_null_alteration(self, field_name, model_name):
raise Exception("Should not have prompted for not null addition")
@@ -459,20 +492,16 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_name_default])
autodetector = MigrationAutodetector(before, after, CustomQuestioner())
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AlterField")
- self.assertEqual(action.name, "name")
- self.assertTrue(action.preserve_default)
- self.assertEqual(action.field.default, 'Ada Lovelace')
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=True)
+ self.assertOperationFieldAttributes(changes, "testapp", 0, 0, default='Ada Lovelace')
def test_alter_field_to_not_null_without_default(self):
- "#23609 - Tests autodetection of nullable to non-nullable alterations"
+ """
+ #23609 - Tests autodetection of nullable to non-nullable alterations.
+ """
class CustomQuestioner(MigrationQuestioner):
def ask_not_null_alteration(self, field_name, model_name):
# Ignore for now, and let me handle existing rows with NULL
@@ -485,20 +514,16 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_name])
autodetector = MigrationAutodetector(before, after, CustomQuestioner())
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AlterField")
- self.assertEqual(action.name, "name")
- self.assertTrue(action.preserve_default)
- self.assertIs(action.field.default, models.NOT_PROVIDED)
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=True)
+ self.assertOperationFieldAttributes(changes, "testapp", 0, 0, default=models.NOT_PROVIDED)
def test_alter_field_to_not_null_oneoff_default(self):
- "#23609 - Tests autodetection of nullable to non-nullable alterations"
+ """
+ #23609 - Tests autodetection of nullable to non-nullable alterations.
+ """
class CustomQuestioner(MigrationQuestioner):
def ask_not_null_alteration(self, field_name, model_name):
# Provide a one-off default now (will be set on all existing rows)
@@ -509,47 +534,35 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_name])
autodetector = MigrationAutodetector(before, after, CustomQuestioner())
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AlterField")
- self.assertEqual(action.name, "name")
- self.assertFalse(action.preserve_default)
- self.assertEqual(action.field.default, "Some Name")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AlterField"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="name", preserve_default=False)
+ self.assertOperationFieldAttributes(changes, "testapp", 0, 0, default="Some Name")
def test_rename_field(self):
- "Tests autodetection of renamed fields"
+ """Tests autodetection of renamed fields."""
# Make state
before = self.make_project_state([self.author_name])
after = self.make_project_state([self.author_name_renamed])
autodetector = MigrationAutodetector(before, after, MigrationQuestioner({"ask_rename": True}))
changes = autodetector._detect_changes()
- # Check
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["RenameField"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name="name", new_name="names")
def test_rename_model(self):
- "Tests autodetection of renamed models"
+ """Tests autodetection of renamed models."""
# Make state
before = self.make_project_state([self.author_with_book, self.book])
after = self.make_project_state([self.author_renamed_with_book, self.book_with_author_renamed])
autodetector = MigrationAutodetector(before, after, MigrationQuestioner({"ask_rename_model": True}))
changes = autodetector._detect_changes()
- # Right number of migrations for model rename?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "RenameModel")
- self.assertEqual(action.old_name, "Author")
- self.assertEqual(action.new_name, "Writer")
+ self.assertOperationTypes(changes, 'testapp', 0, ["RenameModel"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name="Author", new_name="Writer")
# Now that RenameModel handles related fields too, there should be
# no AlterField for the related field.
self.assertNumberMigrations(changes, 'otherapp', 0)
@@ -562,32 +575,23 @@ class AutodetectorTests(TestCase):
# Make state
before = self.make_project_state([self.author_with_book, self.book])
after = self.make_project_state([self.author_renamed_with_book, self.book_with_field_and_author_renamed])
- autodetector = MigrationAutodetector(before, after, MigrationQuestioner({"ask_rename_model": True, "ask_rename": True}))
+ autodetector = MigrationAutodetector(before, after, MigrationQuestioner({
+ "ask_rename": True,
+ "ask_rename_model": True,
+ }))
changes = autodetector._detect_changes()
- # Right number of migrations for model rename?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right actions?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "RenameModel")
- self.assertEqual(action.old_name, "Author")
- self.assertEqual(action.new_name, "Writer")
- # Right number of migrations for related field rename?
+ self.assertOperationTypes(changes, 'testapp', 0, ["RenameModel"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, old_name="Author", new_name="Writer")
+ # Right number/type of migrations for related field rename?
# Alter is already taken care of.
self.assertNumberMigrations(changes, 'otherapp', 1)
- # Right number of actions?
- migration = changes['otherapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right actions?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "RenameField")
- self.assertEqual(action.old_name, "author")
- self.assertEqual(action.new_name, "writer")
+ self.assertOperationTypes(changes, 'otherapp', 0, ["RenameField"])
+ self.assertOperationAttributes(changes, 'otherapp', 0, 0, old_name="author", new_name="writer")
def test_fk_dependency(self):
- "Tests that having a ForeignKey automatically adds a dependency"
+ """Tests that having a ForeignKey automatically adds a dependency."""
# Make state
# Note that testapp (author) has no dependencies,
# otherapp (book) depends on testapp (author),
@@ -596,31 +600,24 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_name, self.book, self.edition])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- self.assertEqual(len(changes['otherapp']), 1)
- self.assertEqual(len(changes['thirdapp']), 1)
- # Right number of actions?
- migration1 = changes['testapp'][0]
- self.assertEqual(len(migration1.operations), 1)
- migration2 = changes['otherapp'][0]
- self.assertEqual(len(migration2.operations), 1)
- migration3 = changes['thirdapp'][0]
- self.assertEqual(len(migration3.operations), 1)
- # Right actions?
- action = migration1.operations[0]
- self.assertEqual(action.__class__.__name__, "CreateModel")
- action = migration2.operations[0]
- self.assertEqual(action.__class__.__name__, "CreateModel")
- action = migration3.operations[0]
- self.assertEqual(action.__class__.__name__, "CreateModel")
- # Right dependencies?
- self.assertEqual(migration1.dependencies, [])
- self.assertEqual(migration2.dependencies, [("testapp", "auto_1")])
- self.assertEqual(migration3.dependencies, [("otherapp", "auto_1")])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
+ self.assertMigrationDependencies(changes, 'testapp', 0, [])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'otherapp', 1)
+ self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="Book")
+ self.assertMigrationDependencies(changes, 'otherapp', 0, [("testapp", "auto_1")])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'thirdapp', 1)
+ self.assertOperationTypes(changes, 'thirdapp', 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, 'thirdapp', 0, 0, name="Edition")
+ self.assertMigrationDependencies(changes, 'thirdapp', 0, [("otherapp", "auto_1")])
def test_proxy_fk_dependency(self):
- "Tests that FK dependencies still work on proxy models"
+ """Tests that FK dependencies still work on proxy models."""
# Make state
# Note that testapp (author) has no dependencies,
# otherapp (book) depends on testapp (authorproxy)
@@ -628,19 +625,21 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_empty, self.author_proxy_third, self.book_proxy_fk])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
+ self.assertMigrationDependencies(changes, 'testapp', 0, [])
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'otherapp', 1)
- self.assertNumberMigrations(changes, 'thirdapp', 1)
- # Right number of actions?
- # Right actions?
self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
- self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="Book")
+ self.assertMigrationDependencies(changes, 'otherapp', 0, [("thirdapp", "auto_1")])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'thirdapp', 1)
self.assertOperationTypes(changes, 'thirdapp', 0, ["CreateModel"])
- # Right dependencies?
- self.assertEqual(changes['testapp'][0].dependencies, [])
- self.assertEqual(changes['otherapp'][0].dependencies, [("thirdapp", "auto_1")])
- self.assertEqual(changes['thirdapp'][0].dependencies, [("testapp", "auto_1")])
+ self.assertOperationAttributes(changes, 'thirdapp', 0, 0, name="AuthorProxy")
+ self.assertMigrationDependencies(changes, 'thirdapp', 0, [("testapp", "auto_1")])
def test_same_app_no_fk_dependency(self):
"""
@@ -658,8 +657,7 @@ class AutodetectorTests(TestCase):
self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
self.assertOperationAttributes(changes, "testapp", 0, 2, name="publisher")
- # Right dependencies?
- self.assertEqual(changes['testapp'][0].dependencies, [])
+ self.assertMigrationDependencies(changes, 'testapp', 0, [])
def test_circular_fk_dependency(self):
"""
@@ -671,24 +669,23 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_with_book, self.book, self.publisher_with_book])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
- self.assertNumberMigrations(changes, 'otherapp', 2)
- # Right types?
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel"])
- self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
- self.assertOperationTypes(changes, 'otherapp', 1, ["AddField"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
- # Right dependencies?
- self.assertEqual(changes['testapp'][0].dependencies, [("otherapp", "auto_1")])
- self.assertEqual(changes['otherapp'][0].dependencies, [])
- self.assertEqual(set(changes['otherapp'][1].dependencies), set([("otherapp", "auto_1"), ("testapp", "auto_1")]))
+ self.assertMigrationDependencies(changes, 'testapp', 0, [("otherapp", "auto_1")])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'otherapp', 2)
+ self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
+ self.assertOperationTypes(changes, 'otherapp', 1, ["AddField"])
+ self.assertMigrationDependencies(changes, 'otherapp', 0, [])
+ self.assertMigrationDependencies(changes, 'otherapp', 1, [("otherapp", "auto_1"), ("testapp", "auto_1")])
def test_same_app_circular_fk_dependency(self):
"""
- Tests that a migration with a FK between two models of the same app
- does not have a dependency to itself.
+ Tests that a migration with a FK between two models of the same app does
+ not have a dependency to itself.
"""
# Make state
before = self.make_project_state([])
@@ -701,14 +698,13 @@ class AutodetectorTests(TestCase):
self.assertOperationAttributes(changes, "testapp", 0, 0, name="Author")
self.assertOperationAttributes(changes, "testapp", 0, 1, name="Publisher")
self.assertOperationAttributes(changes, "testapp", 0, 2, name="publisher")
- # Right dependencies?
- self.assertEqual(changes['testapp'][0].dependencies, [])
+ self.assertMigrationDependencies(changes, 'testapp', 0, [])
def test_same_app_circular_fk_dependency_and_unique_together(self):
"""
- Tests that a migration with circular FK dependency does not try to
- create unique together constraint before creating all required fields first.
- See ticket #22275.
+ #22275 - Tests that a migration with circular FK dependency does not try
+ to create unique together constraint before creating all required fields
+ first.
"""
# Make state
before = self.make_project_state([])
@@ -718,89 +714,45 @@ class AutodetectorTests(TestCase):
# Right number/type of migrations?
self.assertNumberMigrations(changes, 'eggs', 1)
self.assertOperationTypes(changes, 'eggs', 0, ["CreateModel", "CreateModel", "AlterUniqueTogether"])
- self.assertFalse("unique_together" in changes['eggs'][0].operations[0].options)
- self.assertFalse("unique_together" in changes['eggs'][0].operations[1].options)
- # Right dependencies?
- self.assertEqual(changes['eggs'][0].dependencies, [])
-
- def test_unique_together(self):
- "Tests unique_together detection"
- # Make state
- before = self.make_project_state([self.author_empty, self.book])
- after = self.make_project_state([self.author_empty, self.book_unique])
- autodetector = MigrationAutodetector(before, after)
- changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['otherapp']), 1)
- # Right number of actions?
- migration = changes['otherapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AlterUniqueTogether")
- self.assertEqual(action.name, "book")
- self.assertEqual(action.unique_together, set([("author", "title")]))
-
- def test_unique_together_no_changes(self):
- "Tests that unique_togther doesn't generate a migration if no changes have been made"
- # Make state
- before = self.make_project_state([self.author_empty, self.book_unique])
- after = self.make_project_state([self.author_empty, self.book_unique])
- autodetector = MigrationAutodetector(before, after)
- changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes), 0)
+ self.assertNotIn("unique_together", changes['eggs'][0].operations[0].options)
+ self.assertNotIn("unique_together", changes['eggs'][0].operations[1].options)
+ self.assertMigrationDependencies(changes, 'eggs', 0, [])
def test_alter_db_table_add(self):
- """Tests detection for adding db_table in model's options"""
+ """Tests detection for adding db_table in model's options."""
# Make state
before = self.make_project_state([self.author_empty])
after = self.make_project_state([self.author_with_db_table_options])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AlterModelTable")
- self.assertEqual(action.name, "author")
- self.assertEqual(action.table, "author_one")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AlterModelTable"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", table="author_one")
def test_alter_db_table_change(self):
- "Tests detection for changing db_table in model's options'"
+ """Tests detection for changing db_table in model's options'."""
# Make state
before = self.make_project_state([self.author_with_db_table_options])
after = self.make_project_state([self.author_with_new_db_table_options])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AlterModelTable")
- self.assertEqual(action.name, "author")
- self.assertEqual(action.table, "author_two")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AlterModelTable"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", table="author_two")
def test_alter_db_table_remove(self):
- """Tests detection for removing db_table in model's options"""
+ """Tests detection for removing db_table in model's options."""
# Make state
before = self.make_project_state([self.author_with_db_table_options])
after = self.make_project_state([self.author_empty])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AlterModelTable")
- self.assertEqual(action.name, "author")
- self.assertEqual(action.table, None)
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AlterModelTable"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", table=None)
def test_alter_db_table_no_changes(self):
"""
@@ -815,10 +767,10 @@ class AutodetectorTests(TestCase):
# Right number of migrations?
self.assertEqual(len(changes), 0)
- def test_alter_db_table_with_model_change(self):
+ def test_keep_db_table_with_model_change(self):
"""
- Tests when model changes, autodetector does not create more than one
- operation.
+ Tests when model changes but db_table stays as-is, autodetector must not
+ create more than one operation.
"""
# Make state
before = self.make_project_state([self.author_with_db_table_options])
@@ -827,30 +779,52 @@ class AutodetectorTests(TestCase):
before, after, MigrationQuestioner({"ask_rename_model": True})
)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes), 1)
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["RenameModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, old_name="Author", new_name="NewAuthor")
+
+ def test_alter_db_table_with_model_change(self):
+ """
+ Tests when model and db_table changes, autodetector must create two
+ operations.
+ """
+ # Make state
+ before = self.make_project_state([self.author_with_db_table_options])
+ after = self.make_project_state([self.author_renamed_with_new_db_table_options])
+ autodetector = MigrationAutodetector(
+ before, after, MigrationQuestioner({"ask_rename_model": True})
+ )
+ changes = autodetector._detect_changes()
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["RenameModel", "AlterModelTable"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, old_name="Author", new_name="NewAuthor")
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="newauthor", table="author_three")
def test_empty_foo_together(self):
- "#23452 - Empty unique/index_togther shouldn't generate a migration."
+ """
+ #23452 - Empty unique/index_together shouldn't generate a migration.
+ """
# Explicitly testing for not specified, since this is the case after
# a CreateModel operation w/o any definition on the original model
- model_state_not_secified = ModelState("a", "model",
- [("id", models.AutoField(primary_key=True))]
- )
+ model_state_not_secified = ModelState("a", "model", [("id", models.AutoField(primary_key=True))])
# Explicitly testing for None, since this was the issue in #23452 after
# a AlterFooTogether operation with e.g. () as value
- model_state_none = ModelState("a", "model",
- [("id", models.AutoField(primary_key=True))],
- {"unique_together": None, "index_together": None}
- )
+ model_state_none = ModelState("a", "model", [
+ ("id", models.AutoField(primary_key=True))
+ ], {
+ "index_together": None,
+ "unique_together": None,
+ })
# Explicitly testing for the empty set, since we now always have sets.
# During removal (('col1', 'col2'),) --> () this becomes set([])
- model_state_empty = ModelState("a", "model",
- [("id", models.AutoField(primary_key=True))],
- {"unique_together": set(), "index_together": set()}
- )
+ model_state_empty = ModelState("a", "model", [
+ ("id", models.AutoField(primary_key=True))
+ ], {
+ "index_together": set(),
+ "unique_together": set(),
+ })
def test(from_state, to_state, msg):
before = self.make_project_state([from_state])
@@ -876,81 +850,114 @@ class AutodetectorTests(TestCase):
for t in tests:
test(*t)
- def test_unique_together_ordering(self):
- "Tests that unique_together also triggers on ordering changes"
+ def test_add_foo_together(self):
+ """Tests index/unique_together detection."""
# Make state
- before = self.make_project_state([self.author_empty, self.book_unique])
- after = self.make_project_state([self.author_empty, self.book_unique_2])
+ before = self.make_project_state([self.author_empty, self.book])
+ after = self.make_project_state([self.author_empty, self.book_foo_together])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether"])
- self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together={("title", "author")})
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together={("author", "title")})
+ self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", index_together={("author", "title")})
- def test_add_field_and_unique_together(self):
- "Tests that added fields will be created before using them in unique together"
- before = self.make_project_state([self.author_empty, self.book])
- after = self.make_project_state([self.author_empty, self.book_unique_3])
+ def test_remove_foo_together(self):
+ """Tests index/unique_together detection."""
+ before = self.make_project_state([self.author_empty, self.book_foo_together])
+ after = self.make_project_state([self.author_empty, self.book])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, "otherapp", 0, ["AddField", "AlterUniqueTogether"])
- self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", unique_together={("title", "newfield")})
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together=set())
+ self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", index_together=set())
+
+ def test_foo_together_no_changes(self):
+ """
+ Tests that index/unique_together doesn't generate a migration if no
+ changes have been made.
+ """
+ # Make state
+ before = self.make_project_state([self.author_empty, self.book_foo_together])
+ after = self.make_project_state([self.author_empty, self.book_foo_together])
+ autodetector = MigrationAutodetector(before, after)
+ changes = autodetector._detect_changes()
+ # Right number of migrations?
+ self.assertEqual(len(changes), 0)
- def test_remove_field_and_unique_together(self):
- "Tests that removed fields will be removed after updating unique_together"
- before = self.make_project_state([self.author_empty, self.book_unique_3])
- after = self.make_project_state([self.author_empty, self.book_unique])
+ def test_foo_together_ordering(self):
+ """
+ Tests that index/unique_together also triggers on ordering changes.
+ """
+ # Make state
+ before = self.make_project_state([self.author_empty, self.book_foo_together])
+ after = self.make_project_state([self.author_empty, self.book_foo_together_2])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether", "RemoveField"])
- self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together={("author", "title")})
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together={("title", "author")})
+ self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", index_together={("title", "author")})
- def test_rename_field_and_unique_together(self):
- "Tests that removed fields will be removed after updating unique together"
- before = self.make_project_state([self.author_empty, self.book_unique_3])
- after = self.make_project_state([self.author_empty, self.book_unique_4])
- autodetector = MigrationAutodetector(before, after, MigrationQuestioner({"ask_rename": True}))
+ def test_add_field_and_foo_together(self):
+ """
+ Tests that added fields will be created before using them in
+ index/unique_together.
+ """
+ before = self.make_project_state([self.author_empty, self.book])
+ after = self.make_project_state([self.author_empty, self.book_foo_together_3])
+ autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "otherapp", 1)
- self.assertOperationTypes(changes, "otherapp", 0, ["RenameField", "AlterUniqueTogether"])
- self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", unique_together={("title", "newfield2")})
-
- def test_remove_index_together(self):
- author_index_together = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200))
- ], {"index_together": set([("id", "name")])})
+ self.assertOperationTypes(changes, "otherapp", 0, ["AddField", "AlterUniqueTogether", "AlterIndexTogether"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", unique_together={("title", "newfield")})
+ self.assertOperationAttributes(changes, "otherapp", 0, 2, name="book", index_together={("title", "newfield")})
- before = self.make_project_state([author_index_together])
- after = self.make_project_state([self.author_name])
+ def test_remove_field_and_foo_together(self):
+ """
+ Tests that removed fields will be removed after updating
+ index/unique_together.
+ """
+ before = self.make_project_state([self.author_empty, self.book_foo_together_3])
+ after = self.make_project_state([self.author_empty, self.book_foo_together])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- self.assertNumberMigrations(changes, "testapp", 1)
- self.assertOperationTypes(changes, "testapp", 0, ["AlterIndexTogether"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", index_together=set())
-
- def test_remove_unique_together(self):
- author_unique_together = ModelState("testapp", "Author", [
- ("id", models.AutoField(primary_key=True)), ("name", models.CharField(max_length=200))
- ], {"unique_together": set([("id", "name")])})
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["AlterUniqueTogether", "AlterIndexTogether", "RemoveField"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 0, name="book", unique_together={("author", "title")})
+ self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", index_together={("author", "title")})
- before = self.make_project_state([author_unique_together])
- after = self.make_project_state([self.author_name])
- autodetector = MigrationAutodetector(before, after)
+ def test_rename_field_and_foo_together(self):
+ """
+ Tests that removed fields will be removed after updating
+ index/unique_together.
+ """
+ before = self.make_project_state([self.author_empty, self.book_foo_together_3])
+ after = self.make_project_state([self.author_empty, self.book_foo_together_4])
+ autodetector = MigrationAutodetector(before, after, MigrationQuestioner({"ask_rename": True}))
changes = autodetector._detect_changes()
- self.assertNumberMigrations(changes, "testapp", 1)
- self.assertOperationTypes(changes, "testapp", 0, ["AlterUniqueTogether"])
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", unique_together=set())
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["RenameField", "AlterUniqueTogether", "AlterIndexTogether"])
+ self.assertOperationAttributes(changes, "otherapp", 0, 1, name="book", unique_together={
+ ("title", "newfield2")
+ })
+ self.assertOperationAttributes(changes, "otherapp", 0, 2, name="book", index_together={("title", "newfield2")})
def test_proxy(self):
- "Tests that the autodetector correctly deals with proxy models"
+ """Tests that the autodetector correctly deals with proxy models."""
# First, we test adding a proxy model
before = self.make_project_state([self.author_empty])
after = self.make_project_state([self.author_empty, self.author_proxy])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["CreateModel"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="AuthorProxy", options={"proxy": True})
@@ -961,14 +968,17 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_empty, self.author_proxy_notproxy])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["DeleteModel", "CreateModel"])
self.assertOperationAttributes(changes, "testapp", 0, 0, name="AuthorProxy")
self.assertOperationAttributes(changes, "testapp", 0, 1, name="AuthorProxy", options={})
def test_proxy_custom_pk(self):
- "#23415 - The autodetector must correctly deal with custom FK on proxy models."
+ """
+ #23415 - The autodetector must correctly deal with custom FK on proxy
+ models.
+ """
# First, we test the default pk field name
before = self.make_project_state([])
after = self.make_project_state([self.author_empty, self.author_proxy_third, self.book_proxy_fk])
@@ -986,30 +996,34 @@ class AutodetectorTests(TestCase):
self.assertEqual(changes['otherapp'][0].operations[0].fields[2][1].rel.field_name, 'pk_field')
def test_unmanaged(self):
- "Tests that the autodetector correctly deals with managed models"
+ """Tests that the autodetector correctly deals with managed models."""
# First, we test adding an unmanaged model
before = self.make_project_state([self.author_empty])
after = self.make_project_state([self.author_empty, self.author_unmanaged])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="AuthorUnmanaged")
self.assertEqual(changes['testapp'][0].operations[0].options['managed'], False)
+
# Now, we test turning an unmanaged model into a managed model
before = self.make_project_state([self.author_empty, self.author_unmanaged])
after = self.make_project_state([self.author_empty, self.author_unmanaged_managed])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["DeleteModel", "CreateModel"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="AuthorUnmanaged")
self.assertOperationAttributes(changes, 'testapp', 0, 1, name="AuthorUnmanaged")
def test_unmanaged_custom_pk(self):
- "#23415 - The autodetector must correctly deal with custom FK on unmanaged models."
+ """
+ #23415 - The autodetector must correctly deal with custom FK on
+ unmanaged models.
+ """
# First, we test the default pk field name
before = self.make_project_state([])
after = self.make_project_state([self.author_unmanaged_default_pk, self.book])
@@ -1032,30 +1046,23 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.custom_user, self.author_with_custom_user])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes), 1)
- # Check the dependency is correct
- migration = changes['testapp'][0]
- self.assertEqual(migration.dependencies, [("__setting__", "AUTH_USER_MODEL")])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
+ self.assertMigrationDependencies(changes, 'testapp', 0, [("__setting__", "AUTH_USER_MODEL")])
def test_add_field_with_default(self):
- """
- Adding a field with a default should work (#22030).
- """
+ """#22030 - Adding a field with a default should work."""
# Make state
before = self.make_project_state([self.author_empty])
after = self.make_project_state([self.author_name_default])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 1)
- # Right action?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AddField")
- self.assertEqual(action.name, "name")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, name="name")
def test_custom_deconstructable(self):
"""
@@ -1066,7 +1073,8 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_name_deconstructable_2])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- self.assertEqual(changes, {})
+ # Right number of migrations?
+ self.assertEqual(len(changes), 0)
def test_deconstruct_type(self):
"""
@@ -1090,19 +1098,21 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([author])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel"])
def test_replace_string_with_foreignkey(self):
"""
- Adding an FK in the same "spot" as a deleted CharField should work. (#22300).
+ #22300 - Adding an FK in the same "spot" as a deleted CharField should
+ work.
"""
# Make state
before = self.make_project_state([self.author_with_publisher_string])
after = self.make_project_state([self.author_with_publisher, self.publisher])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right result?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "RemoveField", "AddField"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Publisher")
@@ -1118,191 +1128,190 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.author_name]) # removes both the model and FK
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- # Right number of actions?
- migration = changes['testapp'][0]
- self.assertEqual(len(migration.operations), 2)
- # Right actions in right order?
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "RemoveField")
- self.assertEqual(action.name, "publisher")
- action = migration.operations[1]
- self.assertEqual(action.__class__.__name__, "DeleteModel")
- self.assertEqual(action.name, "Publisher")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["RemoveField", "DeleteModel"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, name="publisher")
+ self.assertOperationAttributes(changes, 'testapp', 0, 1, name="Publisher")
def test_add_many_to_many(self):
- """
- Adding a ManyToManyField should not prompt for a default (#22435).
- """
+ """#22435 - Adding a ManyToManyField should not prompt for a default."""
class CustomQuestioner(MigrationQuestioner):
def ask_not_null_addition(self, field_name, model_name):
raise Exception("Should not have prompted for not null addition")
before = self.make_project_state([self.author_empty, self.publisher])
- # Add ManyToManyField to author model
after = self.make_project_state([self.author_with_m2m, self.publisher])
autodetector = MigrationAutodetector(before, after, CustomQuestioner())
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['testapp']), 1)
- migration = changes['testapp'][0]
- # Right actions in right order?
- self.assertEqual(len(migration.operations), 1)
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "AddField")
- self.assertEqual(action.name, "publishers")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'testapp', 1)
+ self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, name="publishers")
def test_create_with_through_model(self):
"""
- Adding a m2m with a through model and the models that use it should
- be ordered correctly.
+ Adding a m2m with a through model and the models that use it should be
+ ordered correctly.
"""
before = self.make_project_state([])
after = self.make_project_state([self.author_with_m2m_through, self.publisher, self.contract])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- # Right actions in right order?
- self.assertOperationTypes(changes, "testapp", 0, ["CreateModel", "CreateModel", "CreateModel", "AddField", "AddField"])
+ self.assertOperationTypes(changes, "testapp", 0, [
+ "CreateModel", "CreateModel", "CreateModel", "AddField", "AddField"
+ ])
+ self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
+ self.assertOperationAttributes(changes, 'testapp', 0, 1, name="Contract")
+ self.assertOperationAttributes(changes, 'testapp', 0, 2, name="Publisher")
+ self.assertOperationAttributes(changes, 'testapp', 0, 3, model_name='contract', name='publisher')
+ self.assertOperationAttributes(changes, 'testapp', 0, 4, model_name='author', name='publishers')
def test_many_to_many_removed_before_through_model(self):
"""
- Removing a ManyToManyField and the "through" model in the same change must remove
- the field before the model to maintain consistency.
+ Removing a ManyToManyField and the "through" model in the same change
+ must remove the field before the model to maintain consistency.
"""
- before = self.make_project_state([self.book_with_multiple_authors_through_attribution, self.author_name, self.attribution])
- after = self.make_project_state([self.book_with_no_author, self.author_name]) # removes both the through model and ManyToMany
+ before = self.make_project_state([
+ self.book_with_multiple_authors_through_attribution, self.author_name, self.attribution
+ ])
+ # Remove both the through model and ManyToMany
+ after = self.make_project_state([self.book_with_no_author, self.author_name])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertEqual(len(changes['otherapp']), 1)
- # Right number of actions?
- migration = changes['otherapp'][0]
- self.assertEqual(len(migration.operations), 4)
- # Right actions in right order?
- # The first two are because we can't optimise RemoveField
- # into DeleteModel reliably.
- action = migration.operations[0]
- self.assertEqual(action.__class__.__name__, "RemoveField")
- self.assertEqual(action.name, "author")
- action = migration.operations[1]
- self.assertEqual(action.__class__.__name__, "RemoveField")
- self.assertEqual(action.name, "book")
- action = migration.operations[2]
- self.assertEqual(action.__class__.__name__, "RemoveField")
- self.assertEqual(action.name, "authors")
- action = migration.operations[3]
- self.assertEqual(action.__class__.__name__, "DeleteModel")
- self.assertEqual(action.name, "Attribution")
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, ["RemoveField", "RemoveField", "RemoveField", "DeleteModel"])
+ self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="author", model_name='attribution')
+ self.assertOperationAttributes(changes, 'otherapp', 0, 1, name="book", model_name='attribution')
+ self.assertOperationAttributes(changes, 'otherapp', 0, 2, name="authors", model_name='book')
+ self.assertOperationAttributes(changes, 'otherapp', 0, 3, name='Attribution')
def test_many_to_many_removed_before_through_model_2(self):
"""
- Removing a model that contains a ManyToManyField and the
- "through" model in the same change must remove
- the field before the model to maintain consistency.
+ Removing a model that contains a ManyToManyField and the "through" model
+ in the same change must remove the field before the model to maintain
+ consistency.
"""
- before = self.make_project_state([self.book_with_multiple_authors_through_attribution, self.author_name, self.attribution])
- after = self.make_project_state([self.author_name]) # removes both the through model and ManyToMany
+ before = self.make_project_state([
+ self.book_with_multiple_authors_through_attribution, self.author_name, self.attribution
+ ])
+ # Remove both the through model and ManyToMany
+ after = self.make_project_state([self.author_name])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
- self.assertNumberMigrations(changes, 'otherapp', 1)
- # Right number of actions?
- self.assertOperationTypes(changes, 'otherapp', 0, ["RemoveField", "RemoveField", "RemoveField", "DeleteModel", "DeleteModel"])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, "otherapp", 1)
+ self.assertOperationTypes(changes, "otherapp", 0, [
+ "RemoveField", "RemoveField", "RemoveField", "DeleteModel", "DeleteModel"
+ ])
+ self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="author", model_name='attribution')
+ self.assertOperationAttributes(changes, 'otherapp', 0, 1, name="book", model_name='attribution')
+ self.assertOperationAttributes(changes, 'otherapp', 0, 2, name="authors", model_name='book')
+ self.assertOperationAttributes(changes, 'otherapp', 0, 3, name='Attribution')
+ self.assertOperationAttributes(changes, 'otherapp', 0, 4, name='Book')
def test_m2m_w_through_multistep_remove(self):
"""
- A model with a m2m field that specifies a "through" model cannot be removed in the same
- migration as that through model as the schema will pass through an inconsistent state.
- The autodetector should produce two migrations to avoid this issue.
+ A model with a m2m field that specifies a "through" model cannot be
+ removed in the same migration as that through model as the schema will
+ pass through an inconsistent state. The autodetector should produce two
+ migrations to avoid this issue.
"""
before = self.make_project_state([self.author_with_m2m_through, self.publisher, self.contract])
after = self.make_project_state([self.publisher])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- # Right actions in right order?
- self.assertOperationTypes(changes, "testapp", 0, ["RemoveField", "RemoveField", "DeleteModel", "RemoveField", "DeleteModel"])
- # Actions touching the right stuff?
- self.assertOperationAttributes(changes, "testapp", 0, 0, name="publishers")
- self.assertOperationAttributes(changes, "testapp", 0, 1, name="author")
+ self.assertOperationTypes(changes, "testapp", 0, [
+ "RemoveField", "RemoveField", "DeleteModel", "RemoveField", "DeleteModel"
+ ])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="publishers", model_name='author')
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="author", model_name='contract')
self.assertOperationAttributes(changes, "testapp", 0, 2, name="Author")
- self.assertOperationAttributes(changes, "testapp", 0, 3, name="publisher")
+ self.assertOperationAttributes(changes, "testapp", 0, 3, name="publisher", model_name='contract')
self.assertOperationAttributes(changes, "testapp", 0, 4, name="Contract")
def test_non_circular_foreignkey_dependency_removal(self):
"""
- If two models with a ForeignKey from one to the other are removed at the same time,
- the autodetector should remove them in the correct order.
+ If two models with a ForeignKey from one to the other are removed at the
+ same time, the autodetector should remove them in the correct order.
"""
before = self.make_project_state([self.author_with_publisher, self.publisher_with_author])
after = self.make_project_state([])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- # Right actions in right order?
self.assertOperationTypes(changes, "testapp", 0, ["RemoveField", "RemoveField", "DeleteModel", "DeleteModel"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="publisher", model_name='author')
+ self.assertOperationAttributes(changes, "testapp", 0, 1, name="author", model_name='publisher')
+ self.assertOperationAttributes(changes, "testapp", 0, 2, name="Author")
+ self.assertOperationAttributes(changes, "testapp", 0, 3, name="Publisher")
def test_alter_model_options(self):
- """
- Changing a model's options should make a change
- """
+ """Changing a model's options should make a change."""
before = self.make_project_state([self.author_empty])
after = self.make_project_state([self.author_with_options])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- # Right actions in right order?
self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, options={
+ "permissions": [('can_hire', 'Can hire')],
+ "verbose_name": "Authi",
+ })
+
# Changing them back to empty should also make a change
before = self.make_project_state([self.author_with_options])
after = self.make_project_state([self.author_empty])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="author", options={})
def test_alter_model_options_proxy(self):
- """
- Changing a proxy model's options should also make a change
- """
+ """Changing a proxy model's options should also make a change."""
before = self.make_project_state([self.author_proxy, self.author_empty])
after = self.make_project_state([self.author_proxy_options, self.author_empty])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, "testapp", 1)
- # Right actions in right order?
self.assertOperationTypes(changes, "testapp", 0, ["AlterModelOptions"])
+ self.assertOperationAttributes(changes, "testapp", 0, 0, name="authorproxy", options={
+ "verbose_name": "Super Author"
+ })
def test_set_alter_order_with_respect_to(self):
- "Tests that setting order_with_respect_to adds a field"
+ """Tests that setting order_with_respect_to adds a field."""
# Make state
before = self.make_project_state([self.book, self.author_with_book])
after = self.make_project_state([self.book, self.author_with_book_order_wrt])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["AlterOrderWithRespectTo"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="author", order_with_respect_to="book")
def test_add_alter_order_with_respect_to(self):
"""
- Tests that setting order_with_respect_to when adding the FK too
- does things in the right order.
+ Tests that setting order_with_respect_to when adding the FK too does
+ things in the right order.
"""
# Make state
before = self.make_project_state([self.author_name])
after = self.make_project_state([self.book, self.author_with_book_order_wrt])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["AddField", "AlterOrderWithRespectTo"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, model_name="author", name="book")
@@ -1310,15 +1319,15 @@ class AutodetectorTests(TestCase):
def test_remove_alter_order_with_respect_to(self):
"""
- Tests that removing order_with_respect_to when removing the FK too
- does things in the right order.
+ Tests that removing order_with_respect_to when removing the FK too does
+ things in the right order.
"""
# Make state
before = self.make_project_state([self.book, self.author_with_book_order_wrt])
after = self.make_project_state([self.author_name])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["AlterOrderWithRespectTo", "RemoveField"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="author", order_with_respect_to=None)
@@ -1334,23 +1343,20 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.book, self.author_with_book_order_wrt])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "AlterOrderWithRespectTo"])
self.assertOperationAttributes(changes, 'testapp', 0, 1, name="author", order_with_respect_to="book")
- # Make sure the _order field is not in the CreateModel fields
self.assertNotIn("_order", [name for name, field in changes['testapp'][0].operations[0].fields])
def test_swappable_first_inheritance(self):
- """
- Tests that swappable models get their CreateModel first.
- """
+ """Tests that swappable models get their CreateModel first."""
# Make state
before = self.make_project_state([])
after = self.make_project_state([self.custom_user, self.aardvark])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'thirdapp', 1)
self.assertOperationTypes(changes, 'thirdapp', 0, ["CreateModel", "CreateModel"])
self.assertOperationAttributes(changes, 'thirdapp', 0, 0, name="CustomUser")
@@ -1358,45 +1364,39 @@ class AutodetectorTests(TestCase):
@override_settings(AUTH_USER_MODEL="thirdapp.CustomUser")
def test_swappable_first_setting(self):
- """
- Tests that swappable models get their CreateModel first.
- """
+ """Tests that swappable models get their CreateModel first."""
# Make state
before = self.make_project_state([])
after = self.make_project_state([self.custom_user_no_inherit, self.aardvark])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'thirdapp', 1)
self.assertOperationTypes(changes, 'thirdapp', 0, ["CreateModel", "CreateModel"])
self.assertOperationAttributes(changes, 'thirdapp', 0, 0, name="CustomUser")
self.assertOperationAttributes(changes, 'thirdapp', 0, 1, name="Aardvark")
def test_bases_first(self):
- """
- Tests that bases of other models come first.
- """
+ """Tests that bases of other models come first."""
# Make state
before = self.make_project_state([])
after = self.make_project_state([self.aardvark_based_on_author, self.author_name])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
self.assertOperationAttributes(changes, 'testapp', 0, 1, name="Aardvark")
def test_proxy_bases_first(self):
- """
- Tests that bases of proxies come first.
- """
+ """Tests that bases of proxies come first."""
# Make state
before = self.make_project_state([])
after = self.make_project_state([self.author_empty, self.author_proxy, self.author_proxy_proxy])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel", "CreateModel"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
@@ -1405,14 +1405,15 @@ class AutodetectorTests(TestCase):
def test_pk_fk_included(self):
"""
- Tests that a relation used as the primary key is kept as part of CreateModel.
+ Tests that a relation used as the primary key is kept as part of
+ CreateModel.
"""
# Make state
before = self.make_project_state([])
after = self.make_project_state([self.aardvark_pk_fk_author, self.author_name])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "CreateModel"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Author")
@@ -1430,12 +1431,11 @@ class AutodetectorTests(TestCase):
after.real_apps = ["migrations"]
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes(graph=loader.graph)
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'otherapp', 1)
self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="Book")
- # Right dependencies?
- self.assertEqual(changes['otherapp'][0].dependencies, [("migrations", "__first__")])
+ self.assertMigrationDependencies(changes, 'otherapp', 0, [("migrations", "__first__")])
@override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
def test_last_dependency(self):
@@ -1451,12 +1451,11 @@ class AutodetectorTests(TestCase):
after.real_apps = ["migrations"]
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes(graph=loader.graph)
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'otherapp', 1)
self.assertOperationTypes(changes, 'otherapp', 0, ["CreateModel"])
self.assertOperationAttributes(changes, 'otherapp', 0, 0, name="Book")
- # Right dependencies?
- self.assertEqual(changes['otherapp'][0].dependencies, [("migrations", "0002_second")])
+ self.assertMigrationDependencies(changes, 'otherapp', 0, [("migrations", "0002_second")])
def test_alter_fk_before_model_deletion(self):
"""
@@ -1468,7 +1467,7 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([self.aardvark_testapp, self.publisher_with_aardvark_author])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["CreateModel", "AlterField", "DeleteModel"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="Aardvark")
@@ -1477,23 +1476,23 @@ class AutodetectorTests(TestCase):
def test_fk_dependency_other_app(self):
"""
- Tests that ForeignKeys correctly depend on other apps' models (#23100)
+ #23100 - Tests that ForeignKeys correctly depend on other apps' models.
"""
# Make state
before = self.make_project_state([self.author_name, self.book])
after = self.make_project_state([self.author_with_book, self.book])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'testapp', 1)
self.assertOperationTypes(changes, 'testapp', 0, ["AddField"])
self.assertOperationAttributes(changes, 'testapp', 0, 0, name="book")
- self.assertEqual(changes['testapp'][0].dependencies, [("otherapp", "__first__")])
+ self.assertMigrationDependencies(changes, 'testapp', 0, [("otherapp", "__first__")])
def test_circular_dependency_mixed_addcreate(self):
"""
- Tests that the dependency resolver knows to put all CreateModel
- before AddField and not become unsolvable (#23315)
+ #23315 - Tests that the dependency resolver knows to put all CreateModel
+ before AddField and not become unsolvable.
"""
address = ModelState("a", "Address", [
("id", models.AutoField(primary_key=True)),
@@ -1514,7 +1513,7 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([address, person, apackage, country])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'a', 2)
self.assertNumberMigrations(changes, 'b', 1)
self.assertOperationTypes(changes, 'a', 0, ["CreateModel", "CreateModel"])
@@ -1524,8 +1523,8 @@ class AutodetectorTests(TestCase):
@override_settings(AUTH_USER_MODEL="a.Tenant")
def test_circular_dependency_swappable(self):
"""
- Tests that the dependency resolver knows to explicitly resolve
- swappable models (#23322)
+ #23322 - Tests that the dependency resolver knows to explicitly resolve
+ swappable models.
"""
tenant = ModelState("a", "Tenant", [
("id", models.AutoField(primary_key=True)),
@@ -1541,22 +1540,23 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([address, tenant])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'a', 2)
- self.assertNumberMigrations(changes, 'b', 1)
self.assertOperationTypes(changes, 'a', 0, ["CreateModel"])
self.assertOperationTypes(changes, 'a', 1, ["AddField"])
+ self.assertMigrationDependencies(changes, 'a', 0, [])
+ self.assertMigrationDependencies(changes, 'a', 1, [('a', 'auto_1'), ('b', 'auto_1')])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'b', 1)
self.assertOperationTypes(changes, 'b', 0, ["CreateModel"])
- self.assertEqual(changes['a'][0].dependencies, [])
- self.assertEqual(set(changes['a'][1].dependencies), set([('a', 'auto_1'), ('b', 'auto_1')]))
- self.assertEqual(changes['b'][0].dependencies, [('__setting__', 'AUTH_USER_MODEL')])
+ self.assertMigrationDependencies(changes, 'b', 0, [('__setting__', 'AUTH_USER_MODEL')])
@override_settings(AUTH_USER_MODEL="b.Tenant")
def test_circular_dependency_swappable2(self):
"""
- Tests that the dependency resolver knows to explicitly resolve
+ #23322 - Tests that the dependency resolver knows to explicitly resolve
swappable models but with the swappable not being the first migrated
- model (#23322)
+ model.
"""
address = ModelState("a", "Address", [
("id", models.AutoField(primary_key=True)),
@@ -1572,21 +1572,22 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([address, tenant])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'a', 2)
- self.assertNumberMigrations(changes, 'b', 1)
self.assertOperationTypes(changes, 'a', 0, ["CreateModel"])
self.assertOperationTypes(changes, 'a', 1, ["AddField"])
+ self.assertMigrationDependencies(changes, 'a', 0, [])
+ self.assertMigrationDependencies(changes, 'a', 1, [('__setting__', 'AUTH_USER_MODEL'), ('a', 'auto_1')])
+ # Right number/type of migrations?
+ self.assertNumberMigrations(changes, 'b', 1)
self.assertOperationTypes(changes, 'b', 0, ["CreateModel"])
- self.assertEqual(changes['a'][0].dependencies, [])
- self.assertEqual(set(changes['a'][1].dependencies), set([('__setting__', 'AUTH_USER_MODEL'), ('a', 'auto_1')]))
- self.assertEqual(changes['b'][0].dependencies, [('a', 'auto_1')])
+ self.assertMigrationDependencies(changes, 'b', 0, [('a', 'auto_1')])
@override_settings(AUTH_USER_MODEL="a.Person")
def test_circular_dependency_swappable_self(self):
"""
- Tests that the dependency resolver knows to explicitly resolve
- swappable models (#23322)
+ #23322 - Tests that the dependency resolver knows to explicitly resolve
+ swappable models.
"""
person = ModelState("a", "Person", [
("id", models.AutoField(primary_key=True)),
@@ -1597,7 +1598,7 @@ class AutodetectorTests(TestCase):
after = self.make_project_state([person])
autodetector = MigrationAutodetector(before, after)
changes = autodetector._detect_changes()
- # Right number of migrations?
+ # Right number/type of migrations?
self.assertNumberMigrations(changes, 'a', 1)
self.assertOperationTypes(changes, 'a', 0, ["CreateModel"])
- self.assertEqual(changes['a'][0].dependencies, [])
+ self.assertMigrationDependencies(changes, 'a', 0, [])