Speed up your functional Django tests

Test should run as fast as possible to really integrate them into your development flow. You can imagine my annoyance when our project with 100+ functional tests took half a minute to run them all. We where already using SQLite’s in memory storage for our tests so that shouldn’t be the problem.

Up until that point we had been using the default Django unittest test case which uses: call_command('flush', verbosity=0, interactive=False). After some profileing I came to the conclusion that most of the time was spend in this call.

Luckily I rememberd a recent post about using transactions for clearing the database state. After changing our tests to use transaction instead of flushing they became a lot quicker. They now run in less than 7 seconds (was 30+ seconds).

The code you see below can be used as a simple drop in replacement for the build-in Django test case. Most of the code has been taken from the normal Django test case, only the transactions are new.

from django.db import transaction
from django.core import mail
from django.test import TestCase as DjangoTestCase
from django.core.management import call_command
from django.conf import settings
from django.core.urlresolvers import clear_url_caches

class TestCase(DjangoTestCase):

    def _pre_setup(self):
        transaction.enter_transaction_management()
        transaction.managed(True)
        if hasattr(self, 'fixtures'):
            # We have to use this slightly awkward syntax due to the fact
            # that we're using *args and **kwargs together.
            call_command('loaddata', *self.fixtures, **{'verbosity': 0})
        if hasattr(self, 'urls'):
            self._old_root_urlconf = settings.ROOT_URLCONF
            settings.ROOT_URLCONF = self.urls
            clear_url_caches()
        mail.outbox = []

    def _post_teardown(self):
        transaction.rollback()
        super(TestCase, self)._post_teardown()
Advertisements

No comments yet

Leave a Reply

Please log in using one of these methods to post your comment:

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

%d bloggers like this: