Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to persist data to DB between tests with pytest-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="[email protected]", 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

like image 956
OG Dude Avatar asked Nov 25 '15 23:11

OG Dude


People also ask

What does pytest Mark Django_db do?

mark. django_db - request database access. This is used to mark a test function as requiring the database.

What is Conftest PY in pytest?

conftest.py is where you setup test configurations and store the testcases that are used by test functions. The configurations and the testcases are called fixture in pytest.

Can you use pytest with Django?

pytest-django is a plugin for pytest that provides a set of useful tools for testing Django applications and projects.

What is pytest Mark Usefixtures?

pytest minimizes the number of active fixtures during test runs. If you have a parametrized fixture, then all the tests using it will first execute with one instance and then finalizers are called before the next fixture instance is created.


1 Answers

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.

like image 180
Antony Hatchkins Avatar answered Oct 16 '22 11:10

Antony Hatchkins