Commit cd809619 authored by Andrew Godwin's avatar Andrew Godwin
Browse files

Autodetector tests

parent c7aa4b53
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -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)
+3 −0
Original line number Diff line number Diff line
@@ -47,6 +47,9 @@ class Migration(object):
    def __repr__(self):
        return "<Migration %s.%s>" % (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
+54 −0
Original line number Diff line number Diff line
# 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")