Pytest-django: 如何在不使用 django_db 标记的情况下允许全局访问数据库?

创建于 2016-09-20  ·  8评论  ·  资料来源: pytest-dev/pytest-django

我正在努力将基于 Django 测试运行器的测试转换为 pytest。
我希望把

import pytest
pytestmark = pytest.mark.django_db

进入属于我的代码的堆栈跟踪的最后一个模块(lib/frontend/decorators.py)
会减轻这种情况,但事实并非如此。 将它放入堆栈跟踪上的所有四个模块也无济于事。

有什么方法可以在 pytest-django 中全局允许数据库访问?

vagrant@vagrant-ubuntu-trusty-64:/vagrant$ pytest 
== test session starts ==
platform linux2 -- Python 2.7.6, pytest-3.0.2, py-1.4.31, pluggy-0.3.1
Django settings: patient.settings (from ini file)
rootdir: /vagrant, inifile: pytest.ini
plugins: django-3.0.0, pythonpath-0.7.1
collected 265 items / 2 errors 

[...]

_ ERROR collecting lib/tests/report/testfunc.py _
lib/tests/report/testfunc.py:6: in <module>
    from report.func import generate_report_filename
lib/report/func.py:29: in <module>
    from frontend import chart
lib/frontend/chart.py:294: in <module>
    @pytest.mark.django_db
lib/frontend/decorators.py:20: in decorator
    if Site.objects.get_current().id in (allowed_site_ids):
/usr/local/lib/python2.7/dist-packages/django/contrib/sites/models.py:60: in get_current
    return self._get_site_by_id(site_id)
/usr/local/lib/python2.7/dist-packages/django/contrib/sites/models.py:39: in _get_site_by_id
    site = self.get(pk=site_id)
/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py:127: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
/usr/local/lib/python2.7/dist-packages/django/db/models/query.py:328: in get
    num = len(clone)
/usr/local/lib/python2.7/dist-packages/django/db/models/query.py:144: in __len__
    self._fetch_all()
/usr/local/lib/python2.7/dist-packages/django/db/models/query.py:965: in _fetch_all
    self._result_cache = list(self.iterator())
/usr/local/lib/python2.7/dist-packages/django/db/models/query.py:238: in iterator
    results = compiler.execute_sql()
/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py:838: in execute_sql
    cursor = self.connection.cursor()
/usr/local/lib/python2.7/dist-packages/django/db/backends/base/base.py:162: in cursor
    cursor = self.make_debug_cursor(self._cursor())
/usr/local/lib/python2.7/dist-packages/django/db/backends/base/base.py:135: in _cursor
    self.ensure_connection()
E   Failed: Database access not allowed, use the "django_db" mark to enable it.

最有用的评论

好吧,您总是可以创建一个自动使用的装置,例如

@pytest.fixture(autouse=True)
def enable_db_access(db):
    pass

在你的会议中

所有8条评论

好吧,您总是可以创建一个自动使用的装置,例如

@pytest.fixture(autouse=True)
def enable_db_access(db):
    pass

在你的会议中

@enkore的答案是要走的路。 我刚刚在文档中添加了一个常见问题解答:

http://pytest-django.readthedocs.io/en/latest/faq.html#how -can-i-give-database-access-to-all-my-tests-without-the-django-db-marker

我在测试中导入的模块在导入时连接到数据库。 如何全局启用数据库访问,以便在测试收集期间已经允许? 谢谢!

@Telofy你有没有解决过使用数据库访问标记导入的问题? 有同样的问题...

抱歉,但 Django(和 pytest-django)的工作方式不可能以可靠的方式运行。 唯一合适的解决方案就是在导入期间不进行数据库查询。 pytest-django 是围绕 pytests 夹具系统构建的,pytest-django 无法确保在导入之前运行夹具。

有关此问题的更详细说明,请参阅我的评论:
https://github.com/pytest-dev/pytest-django/issues/499#issuecomment -322056315

仅仅重写公司的整个平台以避免这些查询不在我的权力或时间预算之内。 我的解决方案是在 conftest.py 中进行超级丑陋的猴子补丁:

from pytest_django.plugin import _blocking_manager
from django.db.backends.base.base import BaseDatabaseWrapper

_blocking_manager.unblock()
_blocking_manager._blocking_wrapper = BaseDatabaseWrapper.ensure_connection

我还使用这个装饰器(与@pytest.mark.django_db )来确保测试没有在错误的数据库上运行,因为预测起来有点复杂:

def assert_test_db(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        assert connection.settings_dict['NAME'] == 'test_kf_server', connection.settings_dict
        return func(*args, **kwargs)
    return wrapper

感谢@Telofy的示例 - 这非常有用。 我还想避免重写我们的整个代码库!

在导入时进行 db 查询不仅会导致错误的 pytest,还会导致其他部分出现难以追踪的问题。 你会过得很糟糕。

您不必重写整个代码库,您可以使用惰性方法/属性来解决它。 在被要求输入值之前不会建立连接的代码。 同样只传递查询集而不进行评估也可以。 避免诸如计数之类的东西

此页面是否有帮助?
0 / 5 - 0 等级