Unit-testing unmanaged Django models

Sat 31 August 2013

Say you have an app with a set of models that aren't being managed by Django, you're going to run into trouble when it comes time to run unit-tests against these. What I mean is if in the model meta you have something like this

class MyClass:
class Meta:
app_label = 'your_app_label'
managed = False
db_table = u'your_table_name'

If you run unit-tests against these models the trouble occurs because django will ignore this model when creating tables in the test database and you'll get a relation not defined error for 'your_table_name'. The solution to this is to create an app specific TestRunner that will over-ride this setting and temporarily allow Django to manage your models, just for testing purposes.

from django.test.simple import DjangoTestSuiteRunner

class ManagedModelTestRunner(DjangoTestSuiteRunner):
Test runner that automatically makes all unmanaged models in your Django
project managed for the duration of the test run, so that one doesn't need
to execute the SQL manually to create them.
def setup_test_environment(self, *args, **kwargs):
from django.db.models.loading import get_models
self.unmanaged_models = [m for m in get_models()
if not m._meta.managed
and m._meta.app_label is 'your_app_label']
for m in self.unmanaged_models:
m._meta.managed = True
super(ManagedModelTestRunner, self).setup_test_environment(*args,

def teardown_test_environment(self, *args, **kwargs):
super(ManagedModelTestRunner, self).teardown_test_environment(*args,
# reset unmanaged models
for m in self.unmanaged_models:
m._meta.managed = False

This code was lovingly taken from hereand extending very slightly to only include models that exist under the 'my_app_label' app. I don't want my app's test to go fudging around with others, unless it's needed.

To then run tests with this testrunner, create a test_settings.py that looks something like this. This which basically tells Django to import your existing settings but to use your newly created TestRunner

from settings import *

TEST_RUNNER = 'your_app_label.scripts.testrunner.ManagedModelTestRunner'

And to run all of the above:

./manage.py test your_app_label --settings=you_app_label.settings.test_settings

Category: Django Tagged: models unit-testing python django


Page 1 of 1