I have tried writing a test on specific migration files. Basically I wanted to test the current state of the database and data between a pair of migrations. I used MigrationExecutor as follows:
executor = MigrationExecutor(connection)
old_apps = executor.loader.project_state(self.migrate_from).apps
executor.migrate(self.migrate_from)
# do something here
executor.migrate(self.migrate_to)
We have so many migration files in the project, so running all of them with unit tests takes a lot of time. Usually, I would set the migration modules to None in the a settings_test.py:
MIGRATION_MODULES: {
'my_app': None
}
With this setting, the test would run really fast. The problem is that the migration files to test (self.migrate_from and self.migrate_to) can no longer be found:
django.db.migrations.exceptions.NodeNotFoundError: Node ('poleluxe', '0090_auto_previous_migration') not a valid node
So I had to include the migration modules again in the test.
Is there a way to include migration files without running all them? In my case, I want to skip all the migrations from 0001 to 0089 and run only 0090 (as self.migration_from) and 0091 (as self.migrate_to).
I'm thinking of squashing the first 89 migrations and put the result in a separate folder together with 0090 and 0091, then refer to that migration folder in the test. However, I'm not sure if this would be a great solution.
This is what I understand so far, please guide me if I'm not correct.
The problem
@override_setting and setUpClass()The Solution
Override MIGRATION_MODULES setting at the very beginning of TestClass even when TestClass was not fully initialized because that's where I only found the right point.
With this way, not only you can disable all migration to speed up when you run your tests but also you can test migration files.
Disable all migration from settings.py.
MIGRATION_MODULES = {app: None for app in INSTALLED_APPS}
--nomigrations options from pytest setting if you use pytest-django.Override 'MIGRATION_MODULES' setting and set it back after test.
class TestMigrations(TestCase):
origin_modules = getattr(settings, 'MIGRATION_MODULES', {})
setattr(settings, 'MIGRATION_MODULES', {})
...
@classmethod
def tearDownClass(cls):
setattr(settings, 'MIGRATION_MODULES', cls.origin_modules)
super().tearDownClass()
Trial Info
@override_setting on TestClass or TestMethod Not working because Django starts and run migration earlier than @override_setting decoration--nomigrations Not working not so sure but my workaround is that disable migrations from Django setting instead of pytest-django