Unit testing django-south datamigrations
Those who use south to manage their migrations perhaps have wondered that would be nice to test them without having to mess with their local test database and usually every time you run a datamigration you want to make sure everything went fine and the data integrity was not compromised, that assumes special importance when for instance your migration is dealing with important records where the consequences of something to go wrong can be catastrophic.
Unfortunately south doesn’t provide any way to test its migrations and when you have to write a migration most of the times you find yourself testing it in your local machine against your own development data and if something fails you will have to replace your previous data and setting your testing environment so you can test it again. If you ever experienced this you know that this repetitive process can become quite a big pain.
Django however have a very good testing framework which becomes even better with django-nose, and not taking advantage of it when testing migrations sounds a bit like a waste of resources.
This was sort of the problem I came across this week and I did a bit of research and found a way to unittest datamigrations in a django testcase.
So imagine you have this migration:
# file: myapp/migrations/0002_some_migration.py
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
"Write your forwards methods here."
# access your orm here
Model1 = orm.Model1
The test would look like:
# file: myapp/tests.py
from django.test import TestCase
from south.migration import Migrations
from myapp.models import Model1
class TestOrm(self):
"""
This class will be used to mock the orm object which goes as a
param to forwards() method
"""
def __init__(self):
setattr(self, 'Model1', Model1)
class MyMigrationTest(TestCase):
def _pick_migration(self, app_label, migration_name):
"""
This method will pick a migration object
"""
migrations = Migrations(app_label)
for migration in migrations:
if migration.full_name().split('.')[-1] == migration_name:
return migration
return None
def test_migration_0002_some_migration(self):
self.migration = self._pick_migration('myapp', '0002_some_migration')
if not self.migration:
return
# running migrations
orm = TestOrm()
self.migration.migration_instance().forwards(orm)
# assertations here
# self.assertEquals(......)
And that’s it.
This of course only covers datamigrations, not schema migrations but I hope this can still be useful.
I don’t know if it is appropriate to create a way to test south migrations in django but if it is I think would be an interesting feature.
Regards
Pingback: Testing django migrations | Something-driven development
I hear your pain – I’ve just posted how I do TDD with both schema and data migrations here:
http://micknelson.wordpress.com/2013/03/01/testing-django-migrations/