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
$ ./manage.py dumpdata potatoes.Potato potatoes.SturdyPotato -o potatoes/fixtures/potatoes_data.json
Load the data
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 @pytest.fixture(scope='session') 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()