具有会话范围的PyTest fixture不保持db数据的连续性

时间:2015-03-11 09:10:01

标签: python django testing pytest

此测试会话正常运行:

from myapp.models import MyModel
@pytest.fixture(scope='function')
def mymodel():
    return G(MyModel)

@pytest.mark.django_db
def test_mymodel_one(mymodel):
    assert MyModel.objects.count() > 0

@pytest.mark.django_db
def test_mymodel_two(mymodel):
    assert MyModel.objects.count() > 0

并生成此输出:

========= test session starts =========
tests/myapp/test_pp.py::test_mymodel_one PASSED
tests/myapp/test_pp.py::test_mymodel_two PASSED

但如果我将灯具的范围更改为'session',则测试2失败:

========= test session starts =========
tests/myapp/test_pp.py::test_mymodel_one PASSED
tests/myapp/test_pp.py::test_mymodel_two FAILED

========= FAILURES ==============
_________ test_mymodel_two ________
tests/myapp/test_pp.py:85: in test_mymodel_two
    assert MyModel.objects.count() > 0
E   assert 0 > 0

创建的对象从fixture中正确返回(我可以访问他的值),但不再存储它。 如何在测试数据库中使用会话范围并维护存储?

1 个答案:

答案 0 :(得分:1)

我试图在我的测试包中复制上下文,并且我发现了你暴露的相同情况。

首先,我想与您分享两页pytest文档,在那里我们可以找到这个问题的答案。 在documentation¹中,方法的组织有点不同,事实上,委托创建夹具的方法是在 conftest.py 中。

    # content of conftest.py
    @pytest.fixture(scope="session")
    def smtp(...):
    # the returned fixture value will be shared for
    # all tests needing it

根据您的测试设置,您可以尝试在conftest模块中移动 mymodel 方法。我试图在conftest文件中移动我的fixture生成器,但由于所需的 django_db 标记,我发现了几个遍历问题,这可能与会话范围冲突(我猜?)。

我还在pytest的示例page中找到了另一个帮助,其中广泛用于不同python模块的会话范围,其中指出内部模块测试不可能访问同一会话范围在父母的同一级别定义。

    # content of a/conftest.py
import pytest

class DB:
    pass

@pytest.fixture(scope="session")
def db():
    return DB()

# content of a/test_db.py
def test_a1(db):
    assert 0, db  # to show value

# content of a/test_db2.py
def test_a2(db):
    assert 0, db  # to show value

如果

# content of b/test_error.py
def test_root(db):  # no db here, will error out
    pass

将无法通过测试,因为

  

a目录中的两个测试模块看到相同的db fixture实例,而sister-directory b中的一个测试看不到它。我们当然也可以在姐妹目录的conftest.py文件中定义数据库夹具。请注意,如果实际需要测试,则仅实例化每个夹具(除非您使用“autouse”夹具,它始终在第一次测试执行之前执行)。

在第二个例子中,我注意到为每个测试实例化了生成fixture的方法,即使范围设置为 session module ,像 function 范围一样工作。

您使用的是哪个版本的pytest?

可以尝试从mympodel方法从当前模块移动到conftest模块吗?