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

About these ads
2 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: