Pytest-django: разрешить тестам обновлять базу данных

У меня есть много маленьких "тестов", которые я использую вручную, то есть запускаю их по требованию. Некоторые из них я хочу изменить в базе данных. Долгое время я использовал для этого pytest. (ситуация - кэширование производственных данных в dev-среде для некоторых специфических тестов и отладки)

Меня убедили добавить pytest-django, у которого есть несколько замечательных возможностей. Он захватил мои ad-hoc тесты; немедленно, они не могут получить доступ или обновить базу данных.

Доступ к базе данных и разрешение обновлений документированы, и я быстро смог наполовину решить эту проблему: включить доступ к базе данных, обновить базу данных во время теста. Но все мои изменения отменяются.

Мое решение сделать это может быть плохим, ну очевидно, что оно работает только наполовину.

Я добавил этот файл: conftest.py в, как кажется, правильное место (тот же каталог, что и тесты).

с содержанием:

import pytest
from django.conf import settings

pytest_plugins = [
    "tests.fixtures.environments",
    "tests.fixtures.initial_data",
]
@pytest.fixture(scope="session")
def django_db_setup():
    settings.DATABASES["default"] = {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'USER': 'django_api_sync',
        'PASSWORD': 'devpassword',
        'NAME': 'django_api_sync',
        'HOST': 'db',
        'PORT': 5432,
    }
    settings.DATABASES["dear_analytics"] ={
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'USER': 'django_api_sync',
        'PASSWORD': 'devpassword',
        'NAME': 'dear_analytics',
        'HOST': 'db',
        'PORT': 5432,
    }



@pytest.fixture
def db_no_rollback(request, django_db_blocker):
    django_db_blocker.unblock()
    request.addfinalizer(django_db_blocker.restore)

и затем я оформляю свой тест, например:

@pytest.mark.django_db
def test_summarise_next_available_data(db_no_rollback):
    KeyValueJson.objects.update_or_create(object_uniqueID="aaa_dear_last_sales_update", defaults={"value": "2020-01-01T00:00:00Z"})
    row = KeyValueJson.objects.filter(object_uniqueID="aaa_dear_last_sales_update").first()
    print(row.value) # this works as expected

...

Он работает нормально. Во время выполнения он обращается к базе данных и обновляет ее, но изменения в базе данных никогда не фиксируются и отступают. Если я остановлю выполнение на точке останова, а затем запрошу таблицу postgresql, то такой строки не будет. Таким образом, похоже, что происходит транзакция, и она откатывается назад.

EDIT

Ах, тест работает, если я удалю @pytest.mark.django_db

или если я сделаю

@pytest.mark.django_db(transaction=True)

Я не понимаю, почему ни один из них не оказывает такого эффекта.

Я думаю, что это работает, когда вы удаляете маркер, потому что тесты django уже имеют доступ к базе данных без маркера:

Тестовые классы, подклассы django.test.TestCase будут иметь доступ к базе данных всегда, чтобы сделать их совместимыми с существующими Django тестами. Тестовые классы, которые подклассифицируют Python's unittest.TestCase, нуждаются в том, чтобы применить маркер, чтобы получить доступ к базе данных.

Когда вы добавляете маркер без указания Transaction=True, по умолчанию Transaction устанавливается в False:

При transaction=False (по умолчанию, если не указано), транзакция операции во время теста не выполняются.

Ссылка: https://pytest-django.readthedocs.io/en/latest/helpers.html#pytest.mark.django_db

Вернуться на верх