Django The Database and Testing


Example

Django uses special database settings when testing so that tests can use the database normally but by default run on an empty database. Database changes in one test will not be seen by another. For example, both of the following tests will pass:

from django.test import TestCase
from myapp.models import Thing

class MyTest(TestCase):

    def test_1(self):
        self.assertEqual(Thing.objects.count(), 0)
        Thing.objects.create()
        self.assertEqual(Thing.objects.count(), 1)

    def test_2(self):
        self.assertEqual(Thing.objects.count(), 0)
        Thing.objects.create(attr1="value")
        self.assertEqual(Thing.objects.count(), 1)

Fixtures

If you want to have database objects used by multiple tests, either create them in the setUp method of the test case. Additionally, if you have defined fixtures in your django project, they can be included like so:

class MyTest(TestCase):
    fixtures = ["fixture1.json", "fixture2.json"]

By default, django is looking for fixtures in the fixtures directory in each app. Further directories can be set using the FIXTURE_DIRS setting:

# myapp/settings.py
FIXTURE_DIRS = [
    os.path.join(BASE_DIR, 'path', 'to', 'directory'),
]

Let's assume you have created a model as follows:

# models.py
from django.db import models


class Person(models.Model):
    """A person defined by his/her first- and lastname."""
    firstname = models.CharField(max_length=255)
    lastname = models.CharField(max_length=255)

Then your .json fixtures could look like that:

# fixture1.json
[
    { "model": "myapp.person",
        "pk": 1,
        "fields": {
            "firstname": "Peter",
            "lastname": "Griffin"
        }
    },
    { "model": "myapp.person",
        "pk": 2,
        "fields": {
            "firstname": "Louis",
            "lastname": "Griffin"
        }
    },
]

Reuse the test-database

To speed up your test-runs you can tell the management-command to reuse the test-database (and to prevent it from being created before and deleted after every test-run). This can be done using the keepdb (or shorthand -k) flag like so:

# Reuse the test-database (since django version 1.8)
$ python manage.py test --keepdb