Making sure South migrations get run when using Django’s create_test_db()

I’ve been experimenting with using Lettuce for a project.  When not using Django’s test runner, you can use the framework’s test database hooks by calling create_test_db() (see the Django docs for create_test_db()) from a method in your terrain.  Django Full Stack Testing and BDD with Lettuce and Splinter is a great resource for seeing how to get up and running.  But, I was having a terrible time because create_test_db() was throwing an exception because it was trying to run the flush management command to flush data on a table that hadn’t yet been created.  According to South’s documentation, “South’s syncdb command will also apply migrations if it’s run in non-interactive mode, which includes when you’re running tests.”

While South’s syncdb command was getting executed by create_test_db(), the option that tells the command to run the migrations after running syncdb, wasn’t getting properly set.  It turns out there is a (not very well documented) workaround, you have to call south.management.commands.patch_for_test_db_setup() before your call to create_test_db().

So, your terrain.py might look something like this:

from lettuce import before, after, world
from django.db import connection
from django.test.utils import setup_test_environment, teardown_test_environment
from south.management.commands import patch_for_test_db_setup
from splinter.browser import Browser

@before.runserver
def setup(server):
# Force running migrations after syncdb.
# syncdb gets run automatically by create_test_db(), and
# South's syncdb (that runs migrations after the default
# syncdb) normally gets called in a test environment, but
# apparently not when calling create_test_db().
# So, we have to use this monkey patched version.
patch_for_test_db_setup()
connection.creation.create_test_db()
setup_test_environment()
world.browser = Browser('webdriver.firefox')

# ...