Pytest-xdist не соблюдает settings.DATABASES (или я делаю что-то неправильно)

Я пытаюсь использовать pytest-xdist для выполнения параллельных тестов. Это работает, и я вижу улучшенную производительность.

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

Я переопределяю эти функции в моем conftest.py.

Поскольку у меня четыре рабочих, я создал четыре базы данных вручную. Затем я использую conftest для изменения settings.DATABASES для проверки DBNAME против DBNAME_

Я проверил, что мой settings.DATABASES изменился и является правильным.

Но запросы все еще идут к старой базе данных DBNAME (которой больше нет в моих settings.DATABASES)

Что может пойти не так?

Нужно ли мне вносить какие-либо другие изменения? Или достаточно внести изменения в приспособление conftest.py?

Заранее спасибо за любую помощь или направление.

EDIT: В моем conftest:py есть много чего. В конце django_db_modify_db_settings_xdist_suffix, если я записываю в лог settings.DATABASES, он показывает мне правильный & ожидаемую информацию. Но запросы по-прежнему идут к разным базам данных. conftest.py одинаков в обоих запусках (pytest -n4 или pytest). Поскольку он зависит от xdist_suffix, он изменяет значение settings.DATABASE только при запуске "-n 4". Две соответствующие функции, которые я считаю важными здесь:

@pytest.fixture(scope="session")
def django_db_setup(
    request,
    django_test_environment,
    django_db_blocker,
    django_db_use_migrations,
    django_db_keepdb,
    django_db_createdb,
    django_db_modify_db_settings,
):
    pass

И

@pytest.fixture(scope="session")
def django_db_modify_db_settings_xdist_suffix(request):
    
    from django.conf import settings

    default = settings.DATABASES["default"].copy()
    settings.DATABASES.clear()
    settings.DATABASES["default"] = default
    xdist_suffix = None
    xdist_worker_id = get_xdist_worker_id(request)
    if xdist_worker_id != 'master':
        xdist_suffix = xdist_worker_id
    if xdist_suffix:

        for db_settings in settings.DATABASES.values():
            test_name = db_settings.get("TEST", {}).get("NAME")

            if not test_name:
                test_name = "test_{}".format(db_settings["NAME"])

            db_settings.setdefault("TEST", {})
            db_settings["TEST"]["NAME"] = "{}_{}".format(test_name, xdist_suffix)
            db_settings["NAME"] = db_settings["TEST"]["NAME"]

Я делаю нечто похожее на то, что сделали вы, но это может показаться более простым или элегантным. На мой взгляд, кажется, что контекст больше на стороне 'Django', чем pytest-xdist.

Я использовал pytest-xdist для масштабирования одновременного стресс-тестирования и крючок, который кажется наиболее релевантным для вашего вопроса, используя gateway-id для отправки параметров удаленному работнику, что позволило провести различие между узлами.

def pytest_configure_node(self, node: WorkerController) -> None:
    """set something peculiar for each node."""
    node.workerinput['SPECIAL'] = get_db_for_node(node.gateway.id)

Попробуйте реализовать функцию, как показано на рисунке для get_db_for_node(gateway_id: str) -> str:

Затем в рабочем вы можете использовать config.workerinput для доступа к специальным параметрам, упомянутым выше:

@pytest.fixture(scope="session")
def special(pytestconfig: Config) -> str:
    if not hasattr(pytestconfig, 'workerinput'):
        log.exception('fixture requires xdist')
        return ''
    return pytestconfig.workerinput['SPECIAL']
Вернуться на верх