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

pytest-django测试后Docker中PostgreSQL数据库未清理问题排查

问题分析与解决方案

核心原因

你遇到的问题大概率是自定义的django_db_setup fixture覆盖了pytest-django默认的事务隔离机制,导致测试结束后没有自动回滚数据。默认情况下,pytest-django会为每个django_db标记的测试开启独立事务,测试完成后回滚,避免数据残留。但你自定义了django_db_setup,跳过了这部分逻辑,测试数据直接写入数据库并持久化,重复测试时就触发唯一键冲突。

具体解决步骤

1. 移除自定义的django_db_setup fixture(推荐)

pytest-django支持通过配置文件或环境变量设置数据库连接,不需要手动重写django_db_setup:

  • 在项目根目录创建pytest.ini,添加数据库配置:
[pytest]
DJANGO_SETTINGS_MODULE = your_project.settings
django_db_host = postgres
django_db_name = name
  • 确保你的Django settings中数据库配置支持通过环境变量或pytest配置覆盖,比如:
# settings.py
import os

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'HOST': os.getenv('DB_HOST', 'localhost'),
        'NAME': os.getenv('DB_NAME', 'default_db'),
        'USER': os.getenv('DB_USER', 'postgres'),
        'PASSWORD': os.getenv('DB_PASSWORD', 'postgres'),
    }
}

这样pytest-django会自动处理数据库初始化和事务回滚,测试数据不会残留。

2. 改用transactional_db标记替代django_db

如果必须保留自定义的django_db_setup,可以把测试标记换成@pytest.mark.transactional_db,强制pytest-django为每个测试开启事务并在结束后回滚:

@pytest.mark.transactional_db  # 替换原来的django_db
@pytest.mark.parametrize("parm1,parm2,expected1,expected2", [
    ('000-01', 'NEW', 'NEW', '000-01'),
    ('000-02', 'NEW2', 'NEW2', '000-02'),
])
def test_add_model(parm1,parm2,expected1,expected2):
    obj = AddModel(field1=parm1, field2=parm2)
    new = obj.create()
    assert new.field1 == expected1
    assert new.field2 == expected2

3. 手动在fixture中添加事务支持

如果需要完全自定义数据库配置,同时保留事务隔离,可以修改django_db_setup fixture,确保启用事务:

import pytest
from django.db import transaction
from django.conf import settings

@pytest.fixture(scope="function")
def django_db_setup():
    settings.DATABASES['default'] = {
        'ENGINE': 'django.db.backends.postgresql',
        'HOST': 'postgres',
        'NAME': 'name',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
    }
    # 确保每个测试都在事务中执行,结束后强制回滚
    with transaction.atomic():
        yield
        transaction.set_rollback(True)

4. Docker层面排查(次要)

如果以上方法无效,检查PostgreSQL容器是否挂载了本地持久化卷:

  • 查看docker-compose.yml,如果数据库服务有volumes配置挂载本地目录,测试后数据会持久化到本地,下次启动容器时数据还在。这种情况可以去掉卷挂载,或者在测试前手动清空数据库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:25:06