【问题标题】:PyTest fixture with session scope does not maintains continuity of db data具有会话范围的 PyTest 夹具不保持数据库数据的连续性
【发布时间】:2015-03-11 09:10:00
【问题描述】:

此测试会话正常工作:

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

但如果我将夹具的范围更改为“会话”,则测试二会失败:

========= 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

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

【问题讨论】:

  • 遇到了同样的问题,当我给我的fixtures模块范围并且在测试类中有一个teardown_method时。 teardown_method 删除了一些由灯具创建的文件。显然scope 是运行或不运行teardownsetup 方法的决定性因素,即使它们只属于test class 并且fixturestest class 之外,被@987654332 使用@.

标签: python django testing pytest


【解决方案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 文件中,但由于需要 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 夹具实例,而姊妹目录 b 中的一个测试没有看到它。我们当然也可以在该姐妹目录的 conftest.py 文件中定义一个 db 固定装置。请注意,只有在实际需要测试时才会实例化每个夹具(除非您使用“自动使用”夹具,它总是在第一个测试执行之前执行)。

在第二个示例中,我注意到生成夹具的方法是为每个测试实例化的,即使范围设置为 sessionmodule,它像 function 作用域一样工作。

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

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

【讨论】:

    猜你喜欢
    • 2020-01-16
    • 1970-01-01
    • 2020-04-27
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多