2

使用以下夹具和测试,测试通过: from deal.models import Deal

@pytest.fixture(scope='function')
def myfixture(django_db_blocker):
    with django_db_blocker.unblock():
        new_deal = Deal()
        new_deal.name = 'Alice'
        new_deal.save()

@pytest.mark.django_db
def test_1(myfixture):
    print(myfixture)
    deals = Deal.objects.all()
    assert deals

@pytest.mark.django_db
def test_2(myfixture):
    print(myfixture)
    deals = Deal.objects.all()
    assert deals

结果:

============ test session starts =============
myapp/tests/pytest_test.py::test_1 PASSED
myapp/tests/pytest_test.py::test_2 PASSED

但是,如果我将范围更改为“模块”,则第二个失败:

@pytest.fixture(scope='module')
def myfixture(django_db_blocker):
    with django_db_blocker.unblock():
        load_deals()

结果:

============ test session starts =============
myapp/tests/pytest_test.py::test_1 PASSED
myapp/tests/pytest_test.py::test_2 FAILED

问题在于数据库没有被持久化,因为我看不到如果我在夹具中返回它,我可以访问创建的交易,但数据库是空的。

========= FAILURES =========
_________ test_2 _________

myfixture = id: 1, name='Alice'

    @pytest.mark.django_db
    def test_2(myfixture):
        print(myfixture)
        deals = Deal.objects.all()
>       assert deals
E       assert <QuerySet []>

如果我只运行 test_2 它当然可以:

============ test session starts =============
myapp/tests/pytest_test.py::test_2 PASSED

我有许多共享相同夹具的测试,如果夹具只能运行一次会快得多,因为 load_deals() 非常慢。

看起来我可以重用名称 django_db_setup 作为夹具,并且 scope='session' 有效,但我需要根据测试运行不同的夹具。

我正在使用 python 3.6.1 - pytest 3.1.2 - pytest-django 3.1.2 和 mariadb 10.1

关于如何使这项工作的任何想法?

4

1 回答 1

0

看起来不像 pytest 问题。

这个对象是Deal什么?查看它的类实现。

还要查看您的数据库功能和函数load_deals()定义。

尝试添加一些日志以查看Deal.objects调用后是否更改Deal.objects.all()

那些 Deal.objects 有可能是 a 的实例generator吗?(python 中的生成器是disposable(仅供一次性使用)对象:

>>> g = ( i for i in range(20))
>>> g
<generator object <genexpr> at 0x101a16f10>
>>> [i for i in g]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> [i for i in g]  # g "has nothing to give"
[]

另请参阅此答案:为什么我不能对相同的数据进行两次迭代?

@ludofet 好的,我现在看到来自 django 的文档 - Deal.objects.all() 将返回一个 QuerySet 对象,它是 iterable 的子类 - 这是一个“一次性使用对象”,这意味着您不能对其进行两次迭代。因此,使用 Deal 对象的第一个测试将通过,第二个将不会在其中找到任何数据。当您的夹具属于“功能”范围时,您的测试通过,因为您的夹具为每个测试创建新的 Deal 对象,因此您只迭代一次。 https://docs.djangoproject.com/en/1.11/ref/models/querysets/#all https://docs.djangoproject.com/en/1.11/ref/models/querysets/#django.db.models.query .QuerySet

于 2017-07-02T04:08:32.050 回答