Monday, August 23, 2010

Django v1.2 and test fixtures

I started using Django test fixtures with unit tests and noticed one interesting issue with the following code:

import unittest

from django.contrib.admin.sites import LOGIN_FORM_KEY
from django.test.client import Client

class SimpleTest(unittest.TestCase):

    fixtures = ['auth.json']

    def setUp(self):
        # Every test needs a client.
        self.client = Client()

        self.super_login = {
                     LOGIN_FORM_KEY: 1,
                     'username': 'myadminuser',
                     'password': 'testing'}

    def testLogin(self):

        from django.contrib.auth.models import User
        print str(User.objects.all())
        # Issue a GET request.
        url = '/admin/'
        response = self.client.get(url)
        self.failUnlessEqual(response.status_code, 200)         # Check that the response is 200 OK.

        print str(self.super_login)
        login =, self.super_login)
        print str(login)        

Before running this test code, I created a fixture by dumping out all the users in the Auth table and storing them into a file stored in the fixtures/ dir of the module:

./ dumpdata --indent=2 auth > apapa/events/fixtures/auth.json

I then created this test case to try to see if the fixture would load:

./ test

I observed that the User table was not populated correctly. The moment though I renamed the apapa/events/fixtures/auth.json to apapa/events/fixtures/initial_data.json, I see this message:

Installing json fixture 'initial_data' from '/data/hg/apapa-caktus/apapa/events/fixtures'.
Installed 1 object(s) from 1 fixture(s)

What's wrong? Well, it turns out whether your unit test code inherits from the Python unittest or the django.test library matters a lot for the fixtures declaration in your code to be used:

from django.test.client import Client
from django.test import TestCase

class SimpleTest(TestCase):

    fixtures = ['auth.json']

The TestCase class in django.test has this code that calls the Django management commands to load the fixture into the database. The Python unittest library, on the other hand, doesn't. Therein lies the issue if you create a unit test case that derives from the wrong class. In this case, you should inherit from the django.test test case to take advantage of the fixtures imports!
for db in databases:
            if hasattr(self, 'fixtures'):
                call_command('loaddata', *self.fixtures, **{
                                                            'verbosity': 0,
                                                            'commit': False,
                                                            'database': db
This thread tipped me off to the issue:

Background info: The initial_data is used to populate a database when you first run syncdb. Take a look at this thread for more info:

No comments:

Post a Comment