Testing Django Migrations with PostgreSQL and Foreign Keys
2025-10-01The incredibly helpful blogpost Writing Unit Tests for Django Migrations delivers what the title
promises. Making testing of migrations.RunPython feasible and easy … as long as you don’t have to fill foreign key
relations on PostgreSQL.
Following the suggested approach, you’ll create records to be migrated in the setUpBeforeMigration method.
class TestLeadSourceMigration(TestMigrations):
migrate_from = "0056_rename_creator_leadsource_created_by_user"
migrate_to = "0057_leadsource_channel_and_more"
def setUpBeforeMigration(self, apps):
Lead = apps.get_model("leadtool", "Lead")
LeadSource = apps.get_model("leadtool", "LeadSource")
lead = Lead.objects.create(
identifier=1,
first_name="Jane",
last_name="Doe",
email="jane.doe@example.com",
)
LeadSource.objects.create(lead=lead)
def test_something(self):
[...]
Running this test will not succeed.
django.db.utils.OperationalError: cannot ALTER TABLE "leadtool_leadsource" because it has pending trigger events
The suggested TestMigrations class is a subclass of TestCase, which executes each test method and associated
lifecycle methods like setUp, and by extension setUpBeforeMigration, in a single transaction. The pending foreign
key trigger events, prevent the ALTER TABLE and any other DDL of the succeeding migration to run.
We have a trivial fix though: inherit from TransactionTestCase. Now the record creation is committed to the database.
Note that the database is reset to a known state by truncating all database tables instead of just rolling back a
transaction, which is slower. Well worth it, though!
PS: Could we please take a moment to appreciate how well the wisdom of that 9.5 year old post held up?
© 2025 Dennis Stritzke
Code samples are public domain unless otherwise noted.