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

指定--reuse-db后测试数据库仍被清空,如何实现预期复用效果?

问题分析与解决方案

首先要明确两个核心概念的区别:

  • --reuse-db 是不同测试运行之间复用数据库结构(避免每次都重建表、跑迁移),不影响同一测试会话内多个测试函数的数据隔离。
  • 你遇到的是同一测试会话中,test1能看到初始用户、test2看不到的问题,本质是测试函数的事务隔离机制导致的数据不共享。

问题根源

  1. 数据库路径修改时机错误:你在django_db_setup fixture中动态修改settings.DATABASES,但pytest-django可能已经在会话初始化阶段建立了数据库连接,导致部分测试函数使用的还是默认测试数据库,而非你指定的test-db.sqlite3。
  2. 事务隔离默认行为:pytest-django默认给每个测试函数包裹独立事务,测试结束后自动回滚。虽然你的初始用户是在会话级fixture中持久化创建的,但SQLite的事务隔离特性或pytest-django的内部逻辑,可能导致后续测试函数无法读取到事务外的持久化数据。

具体解决方案

步骤1:提前设置测试数据库路径

在conftest.py中使用pytest_sessionstart钩子,在会话启动初期就修改数据库配置,避免连接初始化后再修改失效:

def pytest_sessionstart(session):
    from django.conf import settings
    db_path = settings.BASE_DIR / 'test-db.sqlite3'
    settings.DATABASES['default']['NAME'] = db_path

步骤2:调整会话级初始化逻辑

修改django_db_setup fixture,去掉重复修改配置的代码,同时避免重复创建用户:

import pytest
import uuid
from django.contrib.auth.models import User
from django.core.management import call_command


@pytest.fixture(scope='session')
def test_user():
    return {
        'username': uuid.uuid4().hex[:10],
        'password': uuid.uuid4().hex,
    }


@pytest.fixture(scope='session')
def django_db_setup(django_db_blocker, test_user):
    with django_db_blocker.unblock():
        # 仅执行必要的迁移(--reuse-db会保留已有表结构)
        call_command('migrate', '--noinput')
        # 用get_or_create避免重复创建用户
        User.objects.get_or_create(
            username=test_user['username'],
            defaults={
                'password': test_user['password'],
                'email': f'{test_user["username"]}@test',
                'is_active': True,
            }
        )

步骤3:关闭测试函数的事务隔离

给测试函数添加transaction=False标记,让测试直接操作数据库而非在事务中运行,确保能读取到会话级fixture创建的持久化数据:

import pytest


@pytest.mark.django_db(transaction=False)
def test1(django_user_model):
    print(django_user_model.objects.all())


@pytest.mark.django_db(transaction=False)
def test2(django_user_model):
    print(django_user_model.objects.all())

验证效果

运行测试后,test1和test2都会输出包含初始用户的QuerySet,符合你的预期结果。同时--reuse-db会保留test-db.sqlite3数据库,下次运行测试时无需重新创建表和跑迁移,提升启动速度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 18:40:04