From cd809619a270ad48f1a77ee8c32bb0c7d8293f63 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Fri, 7 Jun 2013 15:49:48 +0100 Subject: [PATCH] Autodetector tests --- django/db/migrations/autodetector.py | 16 ++++---- django/db/migrations/migration.py | 3 ++ tests/migrations/test_autodetector.py | 54 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 tests/migrations/test_autodetector.py diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py index 3eea1d7291..ddb14520d3 100644 --- a/django/db/migrations/autodetector.py +++ b/django/db/migrations/autodetector.py @@ -2,7 +2,7 @@ from django.db.migrations import operations from django.db.migrations.migration import Migration -class AutoDetector(object): +class MigrationAutodetector(object): """ Takes a pair of ProjectStates, and compares them to see what the first would need doing to make it match the second (the second @@ -27,9 +27,9 @@ class AutoDetector(object): # We'll store migrations as lists by app names for now self.migrations = {} # Stage one: Adding models. - added_models = set(self.to_state.keys()) - set(self.from_state.keys()) + added_models = set(self.to_state.models.keys()) - set(self.from_state.models.keys()) for app_label, model_name in added_models: - model_state = self.to_state[app_label, model_name] + model_state = self.to_state.models[app_label, model_name] self.add_to_migration( app_label, operations.CreateModel( @@ -40,9 +40,9 @@ class AutoDetector(object): ) ) # Removing models - removed_models = set(self.from_state.keys()) - set(self.to_state.keys()) + removed_models = set(self.from_state.models.keys()) - set(self.to_state.models.keys()) for app_label, model_name in removed_models: - model_state = self.from_state[app_label, model_name] + model_state = self.from_state.models[app_label, model_name] self.add_to_migration( app_label, operations.DeleteModel( @@ -59,11 +59,11 @@ class AutoDetector(object): for migration in migrations: subclass = type("Migration", (Migration,), migration) instance = subclass(migration['name'], app_label) - result.append(instance) + result.add(instance) return result def add_to_migration(self, app_label, operation): migrations = self.migrations.setdefault(app_label, []) if not migrations: - migrations.append({"name": "temp-%i" % len(migrations) + 1, "operations": [], "dependencies": []}) - migrations[-1].operations.append(operation) + migrations.append({"name": "auto_%i" % (len(migrations) + 1), "operations": [], "dependencies": []}) + migrations[-1]['operations'].append(operation) diff --git a/django/db/migrations/migration.py b/django/db/migrations/migration.py index 672e7440ad..ed7fad747b 100644 --- a/django/db/migrations/migration.py +++ b/django/db/migrations/migration.py @@ -47,6 +47,9 @@ class Migration(object): def __repr__(self): return "" % (self.app_label, self.name) + def __hash__(self): + return hash("%s.%s" % (self.app_label, self.name)) + def mutate_state(self, project_state): """ Takes a ProjectState and returns a new one with the migration's diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py new file mode 100644 index 0000000000..8e6a1e4160 --- /dev/null +++ b/tests/migrations/test_autodetector.py @@ -0,0 +1,54 @@ +# encoding: utf8 +from django.test import TransactionTestCase +from django.db.migrations.autodetector import MigrationAutodetector +from django.db.migrations.state import ProjectState, ModelState +from django.db import models + + +class AutodetectorTests(TransactionTestCase): + """ + Tests the migration autodetector. + """ + + author_empty = ModelState("testapp", "Author", [("id", models.AutoField(primary_key=True))]) + + def make_project_state(self, model_states): + "Shortcut to make ProjectStates from lists of predefined models" + project_state = ProjectState() + for model_state in model_states: + project_state.add_model_state(model_state) + return project_state + + def test_new_model(self): + "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.changes() + # Right number of migrations? + self.assertEqual(len(changes), 1) + # Right number of actions? + migration = changes.pop() + self.assertEqual(len(migration.operations), 1) + # Right action? + action = migration.operations[0] + self.assertEqual(action.__class__.__name__, "CreateModel") + self.assertEqual(action.name, "Author") + + def test_old_model(self): + "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.changes() + # Right number of migrations? + self.assertEqual(len(changes), 1) + # Right number of actions? + migration = changes.pop() + self.assertEqual(len(migration.operations), 1) + # Right action? + action = migration.operations[0] + self.assertEqual(action.__class__.__name__, "DeleteModel") + self.assertEqual(action.name, "Author")