So, I've been trying to speed up tests. Surprise. I came across a
fairly easy solution, so I'm sure I must be missing something. If
someone could tell me what I'm missing, I'd really appreciate it.

So, first I created my own subclass of django.test.TestCase:

class MyTestCase(django.test.TestCase):
    # see code below

Then I wrote unit tests, subclassing MyTestCase

class TestParticularThing(MyTestCase):
    fixtures = ['mydata', 'myotherdata.json']
    dirties_db = True

    def test_something(self):
        TestParticularThing.dirties_db = False
        resp = self.client.get('/some/url')
        self.assertContains(resp, 'blah')

    def test_something_else(self):
        TestParticularThing.dirties_db = True
        resp = self.client.post('/another/url', {'var': 'value'})
        self.assertRedirects(resp, '/redirect/url')

So here's the code for MyTestCase. I just overrode the _pre_setup
method so that it checks the dirties_db attribute of the class. If it
both exists and is set to False, flushing and repopulating the db is
skipped, otherwise the db is cleaned as usual.

class MyTestCase(django.test.TestCase):
    def _pre_setup(self):
        """Performs any pre-test setup. This includes:
            * Flushing the database.
            * If the Test Case class has a 'fixtures' member, installing the
              named fixtures.
            * If the Test Case class has a 'urls' member, replace the
              ROOT_URLCONF with it.
            * Clearing the mail test outbox.
        """
        if not hasattr(self.__class__, 'dirties_db') or
self.__class__.dirties_db:
            print "Cleaning db"
            call_command('flush', verbosity=0, interactive=False)
            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.__class__, 'dirties_db'):
            self.__class__.dirties_db = True
        if hasattr(self, 'urls'):
            self._old_root_urlconf = settings.ROOT_URLCONF
            settings.ROOT_URLCONF = self.urls
            clear_url_caches()
        mail.outbox = []

So, to use this, add a class attribute dirties_db = True to your own
subclass of MyTestCase. In any test methods that don't dirty the db,
add:

MyTestCaseSubclass.dirties_db = False

and the next test method that's run in that class won't bother to
flush and repopulate the database. To be explicit, you can set

MyTestCaseSubclass.dirties_db = True

in methods that dirty the database, but if you forget to explicitly
set the value to False, it will be True and the db will be cleaned.

Just trying it on some model and request/response tests, I got a
speed-up from nearly a minute to less than 20 seconds for 13 tests.

So, what am I missing? I know this doesn't deal with doctests--the db
gets cleaned for all of those, but does anyone see when this is just
going to blow up in my face?

Thanks,
Todd

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to