You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+pytest测试中实现describe块内数据持久化的方法

在pytest-describe块中共享Django数据库上下文的解决方案

我完全懂你想要的效果:让同一个describe块里的测试共享数据库状态,只在整个块执行完毕后再统一回滚,而不是每个测试单独回滚。这确实能让describe风格的测试更连贯,还能提升执行效率。

首先说下为什么官方的db_access_without_rollback_and_truncate没生效——这个夹具是模块/会话级的,它会彻底关闭自动回滚和截断,会导致不同describe块之间的数据互相污染,并不是我们需要的「块级隔离+共享」。我们要的是针对单个describe块的事务控制。

解决方案:自定义Class作用域的事务夹具

pytest-describe的每个describe块会被pytest自动转换成一个测试类,所以我们可以利用class作用域的夹具来实现块级的事务管理:

  1. 先定义一个自定义夹具,负责在describe块启动时开启事务,结束时统一回滚:
import pytest
from django.db import transaction

@pytest.fixture(scope="class")
def db_transaction_scope():
    # 关闭自动提交,开启一个顶层事务
    transaction.set_autocommit(False)
    try:
        # 让describe块内的所有测试都在这个事务中执行
        yield
    finally:
        # 块执行完毕后回滚整个事务,恢复初始状态
        transaction.rollback()
        # 恢复自动提交,不影响其他测试
        transaction.set_autocommit(True)
  1. 修改你的测试代码,使用这个夹具并配置django_db允许手动事务管理:
import pytest
from django.contrib.auth import get_user_model

User = get_user_model()

# 应用自定义夹具,并告诉pytest-django我们要手动管理事务
@pytest.mark.usefixtures("db_transaction_scope")
@pytest.mark.django_db(transaction=True)
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()

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

为什么这能生效?

  • db_transaction_scope是class作用域,正好对应一个describe块的生命周期:在块的第一个测试前开启事务,所有测试都在这个事务内操作数据,最后一个测试结束后统一回滚。
  • pytest.mark.django_db(transaction=True)是关键:它告诉pytest-django不要为每个测试自动创建和回滚事务,把事务控制权交给我们的自定义夹具。

注意事项

  • 这种方式只适合有顺序依赖的测试(毕竟你就是要共享上下文),而pytest-describe会按测试定义的顺序执行,所以完全适配。
  • 不要在这个块里执行DDL操作(比如创建/修改表结构),因为Django的事务回滚不支持DDL,会导致数据无法回滚。
  • 如果有嵌套的describe块,你可能需要调整夹具的作用域为module或者针对嵌套块单独处理,但大部分场景下class作用域足够用。

内容的提问来源于stack exchange,提问作者Mattia Larentis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:11:10