【问题标题】:Persistent data among tests with django and pytest使用 django 和 pytest 的测试中的持久数据
【发布时间】:2019-02-27 09:23:20
【问题描述】:

这个问题背后的想法很容易理解,但解决起来很复杂:我需要在测试之间共享数据。

我有一个 Django 项目,我使用 pytest-djangopytest-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,但没有成功,每次测试后数据库仍会重置。

有没有简单的方法来实现这一点?

提前致谢。

【问题讨论】:

标签: django pytest pytest-django


【解决方案1】:

首先警告:请注意,当其中一个测试用例对数据库执行意外操作时,您可能会损害后续测试用例的有效性。回滚是为了确保单元测试的完整性。说了这么多,下面是一个基于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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-16
    • 1970-01-01
    • 2020-06-05
    • 2010-12-01
    • 2018-06-14
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多