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']