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