Постоянные данные среди тестов с django и pytest - PullRequest
0 голосов
/ 27 февраля 2019

Идея этого вопроса проста для понимания, но сложна для решения: мне нужно обмениваться данными между тестами.

У меня есть проект Django, и я использую pytest-django и pytest-descibe для определения и запуска тестов.

В то время как в pytest база данныхоткатывается после каждого теста, в «методе описания» принято делить «контекст» между тестами в рамках одного описания.Это делает написание тестов более читабельным и быстрым для запуска, а также позволяет запускать все утверждения, даже если один тест не проходит между ними.

По этой причине я хотел бы отключить стандартное поведение отката базы данных прикаждый тест и вместо этого выполняйте его после запуска всего описания.

Это упрощенная версия моих тестов:

pytestmark = [pytest.mark.django_db]

def describe_users():
    email = 'foo@example.com'

    def test_create_a_user_and_it_exists():
        User.objects.create(email=email)
        assert User.objects.filter(email=email).exists()  # Pass

    def test_the_user_keeps_to_exist():
        assert User.objects.filter(email=email).exists()  # Fail

Я пытался использовать приспособление db_access_without_rollback_and_truncate предложилв документации, но она не работала, база данных по-прежнему сбрасывается после каждого теста.

Есть ли простой способ добиться этого?

Заранее спасибо.

1 Ответ

0 голосов
/ 27 февраля 2019

Первое предупреждение: помните, что вы можете потенциально поставить под угрозу достоверность последующих тестовых случаев, когда один из них сделает что-то неожиданное с базой данных.Для обеспечения целостности модульного теста существует откат.Сказав это, вот пример, основанный на db_access_without_rollback_and_truncate (сокращено до db_no_rollback):

# Note: do not use pytestmark globally, because it will apply
# rollback access to everything. Instead apply it on an individual basis.

# Use this fixture wherever non-rollback database access is required.
@pytest.fixture
def db_no_rollback(request, django_db_setup, django_db_blocker):
    django_db_blocker.unblock()
    request.addfinalizer(django_db_blocker.restore)

# This test still uses the normal rollback.
@pytest.mark.django_db
def test_start_empty():
    assert MyModel.objects.count() == 0  # PASS

# Create an object here.
def test_1(db_no_rollback):
    item = MyModel.objects.create(title='ABC')
    assert item.id == 1  # PASS

# It still exists here. Then we change it.
def test_2(db_no_rollback):
    item = MyModel.objects.get(title='ABC')
    assert item.id == 1  # PASS
    item.title = 'DEF'
    item.save()

# The change still persists.
def test_3(db_no_rollback):
    assert MyModel.objects.get(id=1).title == 'DEF'  # PASS

# This will pass, but the change won't persist.
@pytest.mark.django_db
def test_4():
    item = MyModel.objects.get(title='DEF')
    assert item.id == 1  # PASS
    item.title = 'GHI'
    item.save()

# This will fail.
@pytest.mark.django_db
def test_5():
    assert MyModel.objects.get(id=1).title == 'GHI'  # FAIL
...