升级pytest至3.5.0后Celery测试失败,添加django_db标记无效求助
我之前也碰到过类似的坑,升级pytest后session级的Celery fixture触发了pytest-django的数据库访问限制。问题核心在于session作用域的fixture和默认function作用域的django_db标记不兼容——你的celery_session_app是session级的,而@pytest.mark.django_db默认只允许function级别的数据库操作,所以哪怕给测试用例加了标记,fixture初始化阶段的数据库访问还是被拦截了。
这里有两个靠谱的解决办法:
方法一:给Celery的session级fixture添加session兼容的数据库标记
直接给celery_session_app和celery_session_worker fixture加上@pytest.mark.django_db(transaction=True)标记,这个参数专门支持session级别的数据库访问:
# conftest.py import pytest from celery.contrib.testing.worker import start_worker from myproject.celery import django_celery_app # 替换成你的Celery app实际导入路径 @pytest.fixture(scope='session') @pytest.mark.django_db(transaction=True) def celery_session_app(request): """Session Fixture: Return app for session fixtures.""" yield django_celery_app @pytest.fixture(scope='session') @pytest.mark.django_db(transaction=True) def celery_session_worker(request, celery_session_app): worker = start_worker(celery_session_app, concurrency=1) worker.start() yield worker worker.stop()
这样Celery应用和worker在session初始化时就能合法访问数据库了,测试用例里的@pytest.mark.django_db标记依然保留,用于function级别的测试操作。
方法二:依赖session级的数据库初始化fixture
如果方法一没生效,可以让Celery的session fixture依赖pytest-django内置的django_db_setup fixture——这是一个session级的fixture,负责完成数据库环境的初始化,能绕过function级的权限限制:
# conftest.py import pytest from celery.contrib.testing.worker import start_worker from myproject.celery import django_celery_app @pytest.fixture(scope='session') def celery_session_app(request, django_db_setup): """Session Fixture: Return app for session fixtures.""" yield django_celery_app @pytest.fixture(scope='session') def celery_session_worker(request, celery_session_app): worker = start_worker(celery_session_app, concurrency=1) worker.start() yield worker worker.stop()
这个方法本质是提前完成数据库的session级初始化,让Celery fixture在合法的环境中运行。
最后提醒下:如果你的Celery任务本身需要在测试中访问数据库,测试用例依然要保留@pytest.mark.django_db(或@pytest.mark.transactional_db)标记,确保任务执行时的数据库权限。
内容的提问来源于stack exchange,提问作者Иван Феофанов

