Populate your Django test database with pytest fixtures

I'm working on a side project that uses data from an external API. For performance reasons I store this data in a local database. But when running pytest, all my tests always start with a clean database. That's not good, as I need the data to run many of the tests, and adding it from the API is very time consuming.

Of course, Django has a solution for this, confusingly called fixtures, and pytest has a way to use Django fixtures in a custom pytest fixture to populate the database with initial test data.

Because it took me a while to find this, I document it here. It works like this:

Dump the data

Using Django's own dumpdata management command, you dump all or selected tables from your local database into a JSON file in a subfolder of the app named fixtures. My Django app is called potatoes, and I want the data for my two models Potato and SturdyPotato.

$ ./manage.py dumpdata potatoes.Potato potatoes.SturdyPotato -o potatoes/fixtures/potatoes_data.json

Load the data

The corresponding loaddata command can be used with pytest's django_db_setup fixture to load the data into the test database.

# tests/conftest.py

import pytest

from django.core.management import call_command

def django_db_setup(django_db_setup, django_db_blocker):
    with django_db_blocker.unblock():
        call_command('loaddata', 'potatoes_data.json')

Use pytest fixture

Now, in every test that needs it, I use this session-scoped fixture, and the test data is available.

# tests/test_models.py

def test_my_potatoes(db, django_db_setup):
    # GIVEN a full database of potatoes, as provided by the django_db_setup fixture
    all_my_potatoes = Potato.objects.all()

Tags: #python # pytest # django # fixture # database # testing Categories: