test_executor.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. from django.test import TransactionTestCase
  2. from django.test.utils import override_settings
  3. from django.db import connection
  4. from django.db.migrations.executor import MigrationExecutor
  5. class ExecutorTests(TransactionTestCase):
  6. """
  7. Tests the migration executor (full end-to-end running).
  8. Bear in mind that if these are failing you should fix the other
  9. test failures first, as they may be propagating into here.
  10. """
  11. available_apps = ["migrations", "django.contrib.sessions"]
  12. @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations"})
  13. def test_run(self):
  14. """
  15. Tests running a simple set of migrations.
  16. """
  17. executor = MigrationExecutor(connection)
  18. executor.recorder.flush()
  19. # Let's look at the plan first and make sure it's up to scratch
  20. plan = executor.migration_plan([("migrations", "0002_second")])
  21. self.assertEqual(
  22. plan,
  23. [
  24. (executor.loader.graph.nodes["migrations", "0001_initial"], False),
  25. (executor.loader.graph.nodes["migrations", "0002_second"], False),
  26. ],
  27. )
  28. # Were the tables there before?
  29. self.assertNotIn("migrations_author", connection.introspection.get_table_list(connection.cursor()))
  30. self.assertNotIn("migrations_book", connection.introspection.get_table_list(connection.cursor()))
  31. # Alright, let's try running it
  32. executor.migrate([("migrations", "0002_second")])
  33. # Are the tables there now?
  34. self.assertIn("migrations_author", connection.introspection.get_table_list(connection.cursor()))
  35. self.assertIn("migrations_book", connection.introspection.get_table_list(connection.cursor()))
  36. # Alright, let's undo what we did
  37. executor.migrate([("migrations", None)])
  38. # Are the tables gone?
  39. self.assertNotIn("migrations_author", connection.introspection.get_table_list(connection.cursor()))
  40. self.assertNotIn("migrations_book", connection.introspection.get_table_list(connection.cursor()))
  41. @override_settings(MIGRATION_MODULES={"migrations": "migrations.test_migrations", "sessions": "migrations.test_migrations_2"})
  42. def test_empty_plan(self):
  43. """
  44. Tests that re-planning a full migration of a fully-migrated set doesn't
  45. perform spurious unmigrations and remigrations.
  46. There was previously a bug where the executor just always performed the
  47. backwards plan for applied migrations - which even for the most recent
  48. migration in an app, might include other, dependent apps, and these
  49. were being unmigrated.
  50. """
  51. # Make the initial plan, check it
  52. # We use 'sessions' here as the second app as it's always present
  53. # in INSTALLED_APPS, so we can happily assign it test migrations.
  54. executor = MigrationExecutor(connection)
  55. plan = executor.migration_plan([("migrations", "0002_second"), ("sessions", "0001_initial")])
  56. self.assertEqual(
  57. plan,
  58. [
  59. (executor.loader.graph.nodes["migrations", "0001_initial"], False),
  60. (executor.loader.graph.nodes["migrations", "0002_second"], False),
  61. (executor.loader.graph.nodes["sessions", "0001_initial"], False),
  62. ],
  63. )
  64. # Fake-apply all migrations
  65. executor.migrate([("migrations", "0002_second"), ("sessions", "0001_initial")], fake=True)
  66. # Now plan a second time and make sure it's empty
  67. plan = executor.migration_plan([("migrations", "0002_second"), ("sessions", "0001_initial")])
  68. self.assertEqual(plan, [])
  69. # Erase all the fake records
  70. executor.recorder.flush()