Pytest-django: pytest.mark.django_db 不适合 setup_module()

创建于 2013-09-14  ·  15评论  ·  资料来源: pytest-dev/pytest-django

这是我的测试代码:

import pytest
pytestmark = pytest.mark.django_db

from handy.db import do_sql, fetch_val

def setup_module(fetch_val):
    print 1
    do_sql('''
        create table test (
            id int primary key,
            tag int not null
        );

        insert into test values (1, 10), (2, 20);
    ''')
    print 2

def test_fetch_val():
    print 3
    assert fetch_val('select min(id) from test') == 1

我从test_fetch_val()得到DatabaseError: relation "test" does not exist test_fetch_val() 。 我也得到

2
Creating test database for alias 'default'...
3

捕获的输出。 看起来setup_module()在创建数据库之前被调用。

最有用的评论

+1 对我来说,只是从一些初始的 Djano 单元测试切换,这是一个主要的缺点,在为我的 API 测试用例初始化数据库时。 实际上支持会话/模块数据库装置应该是一个基本功能。 任何建议如何解决这个问题?

所有15条评论

django_db 标记基于夹具,我不确定如何在夹具和 setup_* 方法之间进行通信。

您可以使用模块范围的夹具来代替实现相同的功能吗? 即像

pytestmark = pytest.mark.usefixture('test_table')

@pytest.fixture(scope='module')
def test_table(db):
    do_sql('create table ...')

def test_fetch_val():
    assert fetch_val('...') == 1

刚试过。 没用。 我现在得到Database access not allowed, use the "django_db" mark to enable
另外, test_table()不会运行(我试图在那里引发异常)

抱歉,应该是usefixtures,而不是usefixture:

http://pytest.org/latest/fixture.html#usefixtures

现在我得到ScopeMismatchError: You tried to access the 'function' scoped funcarg 'db' with a 'module' scoped request object, involved factories

从参数中删除db参数会导致夹具失败,删除 scope='module' 使认为可行,但随后为每个测试运行test_table() ,这是我不想要的。

我也试过

pytestmark = pytest.mark.django_db

@pytest.fixture(scope='module')
def test_table():
    do_sql('''
        create table test (
            id int primary key,
            tag int not null
        );

        insert into test values (1, 10), (2, 20);
    ''')

def test_fetch_val(test_table):
    assert fetch_val('select min(id) from test') == 1

def test_fetch_val2(test_table):
    assert fetch_val('select min(id) from test') == 1

这几乎有效,但第二次测试以某种方式失败了DatabaseError: relation "test" does not exist 。 对我来说完全是个谜。

Django 和 django_db 标记以每个测试用例在其自己的事务中运行的方式工作,因此将 django_db 与将数据插入数据库的模块级固定装置一起使用并没有真正意义。

你的用例是什么? 为什么您在测试中“手动”创建数据库表,而不是使用 Django,但仍想使用 Django 的测试数据库/测试数据库游标?

您不能通过构建一个普通的数据库游标来实现您所追求的目标吗?

(最后一个示例避免了 ScopeMismatchError,但它在测试中失败了,因为事务在第一次测试后回滚,因此回滚了测试表。)

我正在尝试测试几个在内部使用 django 游标的低级数据库实用程序 - https://github.com/Suor/handy/blob/master/handy/db.py#L40

而且我发现在models.py定义模型然后在某些 django 格式中定义夹具来测试它会更加混乱。 这将是总共 3 个文件来测试非常基本的功能。

我只想在运行测试之前执行一些初始化代码,以便我可以使用一些数据。

哦,我成功了! 将初始化 SQL 包装到begin; ... commit;有所帮助。

非常感谢您提供的所有提示。

这是一个对我来说看起来有点脆弱的黑客。 我可能会设置一个额外的应用程序,该应用程序仅用于使用简单模型进行测试,然后您可以使用它来运行这些函数。 然后,您可以轻松地使用 Django 的 ORM 来填充测试中的数据。 它的输入稍微多一些,还有一些额外的文件,但是对于将来的损坏应该是安全的。

如果其他人发现这个问题:在 setup_function/setup_class/setup_module 中进行数据库设置并不真正支持或不可能以任何好的方式进行,因为 pytest-django 的数据库设置基于夹具。

解决方案是使用正确请求 db 夹具的夹具:
http://pytest-django.readthedocs.org/en/latest/helpers.html#db

@pelme
使用db固定装置,可以仅在函数范围内运行此类设置,而不是在类、模块或会话上。 例如,如果我们需要在执行类测试之前将一些记录填充到数据库中。

==================================== ERRORS ====================================
___________ ERROR at setup of TestHistoryAlerts.test_one_point_data ____________
ScopeMismatch: You tried to access the 'function' scoped fixture 'db' with a 'session' scoped request object, involved factories
tests/conftest.py:140:  def ts(db)
../../../../.virtualenvs/app/lib/python2.7/site-packages/pytest_django/fixtures.py:158:  def db(request, _django_db_setup, _django_cursor_wrapper)

有没有其他方法来处理它?

是的,这是当前实施的 db 固定装置的限制。 在 PR #258 中,有一些工作可以创建受类/模块/会话范围约束的数据库状态。

即使这个问题已经很老了,我发现找到解决pytestpytest-django问题的解决方案很有用。 由于pytest 3.5.0使用django_db标记和module级别装置时存在问题。

下面是在3.5.0之前工作的(至少它没有引起任何问题)。

@pytest.fixture(scope='module')
def user():
    return User.objects.create(...)

@pytest.mark.django_db
def test_some_case(user):
    pass

3.5.0它提出

Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.

解决方案是删除scope='module'

+1 对我来说,只是从一些初始的 Djano 单元测试切换,这是一个主要的缺点,在为我的 API 测试用例初始化数据库时。 实际上支持会话/模块数据库装置应该是一个基本功能。 任何建议如何解决这个问题?

+1

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

相关问题

blueyed picture blueyed  ·  7评论

mpasternak picture mpasternak  ·  5评论

WoLpH picture WoLpH  ·  7评论

asfaltboy picture asfaltboy  ·  5评论

aljosa picture aljosa  ·  8评论