Django Test Migrations

1.5.0 · active · verified Tue Apr 14

django-test-migrations is a Python library designed for robustly testing Django schema and data migrations, ensuring they apply correctly, roll back safely, and maintain data integrity. It supports testing migration order and names, and works across multiple Django versions (currently 3.2, 4.1, 4.2, 5.0, 5.2). The library is actively maintained with regular updates for Python and Django version compatibility. The current version is 1.5.0, released on April 18, 2025.

Warnings

Install

Imports

Quickstart

The quickstart demonstrates using the `Migrator` class with `pytest` to test a specific migration. It outlines how to set up the database to an 'initial' state before the migration, create test data using the 'old' model state, apply the migration, and then assert the results using the 'new' model state. It emphasizes accessing models through `old_state.apps.get_model()` and `new_state.apps.get_model()` to ensure correct historical model versions are used.

import os
import pytest
from django.conf import settings

# Minimal Django settings for testing if not already configured
# In a real project, this would typically be in your settings.py
if not settings.configured:
    settings.configure(
        INSTALLED_APPS=[
            'django.contrib.admin',
            'django.contrib.auth',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.messages',
            'django.contrib.staticfiles',
            # Add your app here, e.g., 'myapp'
        ],
        DATABASES={
            'default': {
                'ENGINE': 'django.db.backends.sqlite3',
                'NAME': ':memory:',
            }
        },
        MIGRATION_MODULES={ # Example for a hypothetical app 'myapp'
            # 'myapp': 'myapp.migrations' # Uncomment if your app has migrations
        }
    )

from django_test_migrations.migrator import Migrator

@pytest.fixture(scope='function')
def migrator(db) -> Migrator:
    """Provides a Migrator instance for testing against the 'default' database."""
    return Migrator(database='default')

def test_my_migration(migrator: Migrator):
    # Set up the database to a state *before* the migration you want to test
    # Example: app_label 'myapp', migration name '0001_initial'
    old_state = migrator.apply_initial_migration(('myapp', '0001_initial'))

    # Get the model class from the old state
    # Replace 'MyModel' with your actual model name
    OldMyModel = old_state.apps.get_model('myapp', 'MyModel')

    # Create some data that will be affected by the migration
    # Example: creating an instance with an old field value
    old_instance = OldMyModel.objects.create(some_old_field='value')

    # Apply the migration you want to test
    # Example: app_label 'myapp', migration name '0002_new_field'
    new_state = migrator.apply_tested_migration(('myapp', '0002_new_field'))

    # Get the model class from the new state
    NewMyModel = new_state.apps.get_model('myapp', 'MyModel')

    # Assertions: Check that the data was migrated correctly
    new_instance = NewMyModel.objects.get(pk=old_instance.pk)
    assert hasattr(new_instance, 'some_new_field') # Check for new field
    # assert new_instance.some_new_field == 'expected_new_value'

    # Optional: Test rollback
    # migrator.reset()
    # assert not NewMyModel.objects.filter(pk=old_instance.pk).exists() # Or check rolled back state

view raw JSON →