From 457cfd6f393511a207e3400184ff03813818afa5 Mon Sep 17 00:00:00 2001 From: David Wobrock Date: Mon, 13 Jun 2022 08:21:15 +0200 Subject: [PATCH] Refs #27236 -- Added test_autodetector.BaseAutodetectorTests. --- tests/migrations/test_autodetector.py | 378 +++++++++++++------------- 1 file changed, 190 insertions(+), 188 deletions(-) diff --git a/tests/migrations/test_autodetector.py b/tests/migrations/test_autodetector.py index 33411c9e3e..14a1faa50c 100644 --- a/tests/migrations/test_autodetector.py +++ b/tests/migrations/test_autodetector.py @@ -31,7 +31,196 @@ class DeconstructibleObject: return (self.__module__ + "." + self.__class__.__name__, self.args, self.kwargs) -class AutodetectorTests(TestCase): +class BaseAutodetectorTests(TestCase): + def repr_changes(self, changes, include_dependencies=False): + output = "" + for app_label, migrations_ in sorted(changes.items()): + output += " %s:\n" % app_label + for migration in migrations_: + 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): + if len(changes.get(app_label, [])) != number: + self.fail( + "Incorrect number of migrations (%s) for %s (expected %s)\n%s" + % ( + len(changes.get(app_label, [])), + app_label, + number, + self.repr_changes(changes), + ) + ) + + def assertMigrationDependencies(self, changes, app_label, position, 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]) < position + 1: + self.fail( + "No migration at index %s for %s\n%s" + % (position, app_label, self.repr_changes(changes)) + ) + migration = changes[app_label][position] + 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, position, types): + 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]) < position + 1: + self.fail( + "No migration at index %s for %s\n%s" + % (position, app_label, self.repr_changes(changes)) + ) + migration = changes[app_label][position] + real_types = [ + operation.__class__.__name__ for operation in migration.operations + ] + if types != real_types: + self.fail( + "Operation type mismatch for %s.%s (expected %s):\n%s" + % ( + app_label, + migration.name, + types, + self.repr_changes(changes), + ) + ) + + def assertOperationAttributes( + self, changes, app_label, position, operation_position, **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]) < position + 1: + self.fail( + "No migration at index %s for %s\n%s" + % (position, app_label, self.repr_changes(changes)) + ) + migration = changes[app_label][position] + if len(changes[app_label]) < position + 1: + self.fail( + "No operation at index %s for %s.%s\n%s" + % ( + operation_position, + app_label, + migration.name, + self.repr_changes(changes), + ) + ) + operation = migration.operations[operation_position] + for attr, value in attrs.items(): + if getattr(operation, attr, None) != value: + self.fail( + "Attribute mismatch for %s.%s op #%s, %s (expected %r, got %r):\n%s" + % ( + app_label, + migration.name, + operation_position, + attr, + value, + getattr(operation, attr, None), + self.repr_changes(changes), + ) + ) + + def assertOperationFieldAttributes( + self, changes, app_label, position, operation_position, **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]) < position + 1: + self.fail( + "No migration at index %s for %s\n%s" + % (position, app_label, self.repr_changes(changes)) + ) + migration = changes[app_label][position] + if len(changes[app_label]) < position + 1: + self.fail( + "No operation at index %s for %s.%s\n%s" + % ( + operation_position, + app_label, + migration.name, + self.repr_changes(changes), + ) + ) + operation = migration.operations[operation_position] + if not hasattr(operation, "field"): + self.fail( + "No field attribute for %s.%s op #%s." + % ( + app_label, + migration.name, + operation_position, + ) + ) + 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_position, + 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() + for model_state in model_states: + project_state.add_model(model_state.clone()) + return project_state + + def get_changes(self, before_states, after_states, questioner=None): + if not isinstance(before_states, ProjectState): + before_states = self.make_project_state(before_states) + if not isinstance(after_states, ProjectState): + after_states = self.make_project_state(after_states) + return MigrationAutodetector( + before_states, + after_states, + questioner, + )._detect_changes() + + +class AutodetectorTests(BaseAutodetectorTests): """ Tests the migration autodetector. """ @@ -954,193 +1143,6 @@ class AutodetectorTests(TestCase): }, ) - def repr_changes(self, changes, include_dependencies=False): - output = "" - for app_label, migrations_ in sorted(changes.items()): - output += " %s:\n" % app_label - for migration in migrations_: - 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): - if len(changes.get(app_label, [])) != number: - self.fail( - "Incorrect number of migrations (%s) for %s (expected %s)\n%s" - % ( - len(changes.get(app_label, [])), - app_label, - number, - self.repr_changes(changes), - ) - ) - - def assertMigrationDependencies(self, changes, app_label, position, 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]) < position + 1: - self.fail( - "No migration at index %s for %s\n%s" - % (position, app_label, self.repr_changes(changes)) - ) - migration = changes[app_label][position] - 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, position, types): - 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]) < position + 1: - self.fail( - "No migration at index %s for %s\n%s" - % (position, app_label, self.repr_changes(changes)) - ) - migration = changes[app_label][position] - real_types = [ - operation.__class__.__name__ for operation in migration.operations - ] - if types != real_types: - self.fail( - "Operation type mismatch for %s.%s (expected %s):\n%s" - % ( - app_label, - migration.name, - types, - self.repr_changes(changes), - ) - ) - - def assertOperationAttributes( - self, changes, app_label, position, operation_position, **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]) < position + 1: - self.fail( - "No migration at index %s for %s\n%s" - % (position, app_label, self.repr_changes(changes)) - ) - migration = changes[app_label][position] - if len(changes[app_label]) < position + 1: - self.fail( - "No operation at index %s for %s.%s\n%s" - % ( - operation_position, - app_label, - migration.name, - self.repr_changes(changes), - ) - ) - operation = migration.operations[operation_position] - for attr, value in attrs.items(): - if getattr(operation, attr, None) != value: - self.fail( - "Attribute mismatch for %s.%s op #%s, %s (expected %r, got %r):\n%s" - % ( - app_label, - migration.name, - operation_position, - attr, - value, - getattr(operation, attr, None), - self.repr_changes(changes), - ) - ) - - def assertOperationFieldAttributes( - self, changes, app_label, position, operation_position, **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]) < position + 1: - self.fail( - "No migration at index %s for %s\n%s" - % (position, app_label, self.repr_changes(changes)) - ) - migration = changes[app_label][position] - if len(changes[app_label]) < position + 1: - self.fail( - "No operation at index %s for %s.%s\n%s" - % ( - operation_position, - app_label, - migration.name, - self.repr_changes(changes), - ) - ) - operation = migration.operations[operation_position] - if not hasattr(operation, "field"): - self.fail( - "No field attribute for %s.%s op #%s." - % ( - app_label, - migration.name, - operation_position, - ) - ) - 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_position, - 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() - for model_state in model_states: - project_state.add_model(model_state.clone()) - return project_state - - def get_changes(self, before_states, after_states, questioner=None): - if not isinstance(before_states, ProjectState): - before_states = self.make_project_state(before_states) - if not isinstance(after_states, ProjectState): - after_states = self.make_project_state(after_states) - return MigrationAutodetector( - before_states, - after_states, - questioner, - )._detect_changes() - def test_arrange_for_graph(self): """Tests auto-naming of migrations for graph matching.""" # Make a fake graph