прибор pytest-django с scope = 'module' работает только для первого теста

Со следующими приспособлениями и тестами тесты проходят: 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

Есть идеи, как это сделать?


person ludofet    schedule 28.06.2017    source источник
comment
Возможно, связанная проблема Github в pytest-django   -  person Christian Long    schedule 07.04.2020


Ответы (1)


Не похоже на проблему pytest.

Что это за объект Deal? Посмотрите на реализацию этого класса.

Также изучите функциональность вашей базы данных и определение функции load_deals().

Попробуйте добавить запись в журнал, чтобы увидеть, не изменится ли Deal.objects после вызова Deal.objects.all()

Возможно ли, что эти объекты Deal.objects являются экземпляром 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

person Dmitry Tokarev    schedule 02.07.2017
comment
Сделка - это модель джанго. Я обновил пример, чтобы прояснить его. Deal.objects.all () - это функция django для получения всех сделок из базы данных. Никакого преобразования не происходит. - person ludofet; 02.07.2017