django - django 和 pytest 测试之间的持久数据

标签 django pytest pytest-django

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

我有一个 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

我尝试使用 fixture db_access_without_rollback_and_truncate文档中建议但它不起作用,每次测试后数据库仍会重置。

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

提前致谢。

最佳答案

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

关于django - django 和 pytest 测试之间的持久数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54901966/

相关文章:

python - 升级pytest导致TypeError : 'NoneType' object is not callable error

python - 如何使用pytest-qt点击QMessageBox?

python - py.test 未正确从 conftest 导入模块 - 失败并显示 ConftestImportFailure : ModuleNotFound

django - pytest-django:设置用户权限

python - 使用 pytest-django 在参数化测试之间保存数据

django - 我怎样才能在 Django 中拥有同一个模型的两个外键?

django - 忽略 Django 中的请求

django - 如何为不同的应用程序组合 Django Rest Framework 路由器

python - 如何使用 pytest 在 Django 中测试重定向?

python - 查询集 : LEFT JOIN with AND