Test-Driven Development with Django & South
I’d basically given up on attempting test-driven with Django, given
the project I’m currently working on uses models with a lot of
South migrations. Just building the
database and running the migrations could take a minute or so when
running manage.py test
, and resetting the database to a clean state
meant the test suite would take several minutes to run.
I’ve had an idea in the back of my mind for a while, and today I finally got around to making it work.
SQLite
When using SQLite, the test runner doesn’t bother to actually hit the
filesystem, it just does the whole thing in
memory,
which is a good deal quicker. Previously, I couldn’t use SQLite,
because South doesn’t like it (since SQLite doesn’t support ALTER TABLE
).
My realisation was that if I turned off South, I could use SQLite, which I did with this rather hackish file called test_settings.py
:
from settings import *
INSTALLED_APPS = [app for app in INSTALLED_APPS if app != 'south']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'test_database.db'
}
}
I can then do a quick run of the test suite using:
manage.py test --settings=test_settings
Obviously, this doesn’t run through my South migrations, which I probably should do from time to time (especially when adding new migrations). I can still test those with:
manage.py test
since by default the test runner will hit my normal settings module,
which still has South in INSTALLED_APPS
, and which hits my MySQL
database.
The Results
With my test_settings
, I get the following output:
Ran 121 tests in 3.218s
With my default settings, I get:
Ran 121 tests in 326.742s
If I run tests for a particular app (which is generally all I need to do), that difference is 0.312s to 31.064s.
That makes my test run approximately 99% quicker, and well within what I consider an acceptable time to run every time I make small changes to my code.