How to persist data to DB between tests with pytest-django

djangopytestpytest-django

How can I persist data to DB when using pytest/pytest-django in a test-run of a Django application?

I run pytest with py.test --nomigrations --reuse-db -s and the Postgres DB test_<configued_db_name> is created as expected, however nothing seems to be persisted to DB between tests and at the end of the test run the DB is empty.

import pytest
from django.contrib.auth.models import User


@pytest.mark.django_db(transaction=False)
def test_insert_user():
    user = User.objects.create_user(username="test_user", email="test_user@test.com", password="test")
    users = User.objects.all()
    assert len(users) > 0

@pytest.mark.django_db(transaction=False)
def test_check_user():
    users = User.objects.all()
    assert len(users) > 0

The first test passes, the second does not making me wonder if anything is persisted to DB at all. According to the pystest-django documentation @pytest.mark.django_db(transaction=False) will not rollback whatever has been affected by the decorated test.

Thank you,

/David

Best Answer

Another way of prefilling the database with data for each function is like that:

import pytest

from django.contrib.auth.models import User

@pytest.fixture(scope='module')
def django_db_setup(django_db_setup, django_db_blocker):
    print('setup')
    with django_db_blocker.unblock():
        User.objects.create(username='a')
        assert set(u.username for u in User.objects.all()) == {'a'}

@pytest.mark.django_db
def test1():
    print('test1')
    User.objects.create(username='b')
    assert set(u.username for u in User.objects.all()) == {'a', 'b'}

@pytest.mark.django_db
def test2():
    print('test2')
    User.objects.create(username='c')
    assert set(u.username for u in User.objects.all()) == {'a', 'c'}

The good thing about this method is that the setup function is only called once:

plugins: django-3.1.2
collected 2 items

mytest.py setup
test1
.test2
.
=================== 2 passed in 1.38 seconds ====================

The bad thing is that 1.38 seconds is a bit too much for such a simple test. --reuse-db is a faster way to do it.