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, **kwargs) def teardown_test_environment(self, *args, **kwargs): super(ManagedModelTestRunner, self).teardown_test_environment(*args, **kwargs) # 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