You need to enable JavaScript to run this app. Django使用pytest时未创建测试库且测试数据位置不明的问题
优惠活动
大模型
产品
解决方案
定价
更多

Django使用pytest时未创建测试库且测试数据位置不明的问题

问题根因

你的异常是三层配置与代码缺陷叠加导致的,完全不符合pytest-django的测试隔离预期:

1. 核心配置缺失,测试库创建逻辑未触发

pytest-django的test_前缀独立测试库创建机制,仅在插件正常加载、且测试代码被标记为允许数据库访问时才会触发。
你当前的配置存在基础缺陷:

  • 仅在pytest.ini中配置了DJANGO_SETTINGS_MODULE,但未确认pytest-django插件是否正常安装、被pytest进程加载。如果插件未加载,@pytest.mark.django_db只是一个无实际作用的自定义标记,不会执行任何数据库拦截、测试库切换、事务回滚的逻辑。
  • 这种场景下,所有测试代码会直接按照settings.py中的数据库配置连接原有loc_db业务库,完全不会触发test_loc_db的创建流程,所有写入操作直接落到生产业务库中。

2. 自定义序列化器逻辑存在冗余,导致测试结果失真

你实现的BulkUpdateOrCreateListSerializer批量创建逻辑存在重复写入问题:

  • 循环调用self.child.create(attrs)时,每个子序列化器接收到的data是单个字典,会触发SnippetSerializer.create方法中的instance.save()逻辑,每循环一次就向数据库写入一条持久化记录。
  • 拿到所有已持久化的实例后,又额外执行一次bulk_create批量插入,这一步理论上会触发主键重复的完整性约束错误。
  • 你看到测试用例“判定通过”,本质是因为没有测试隔离逻辑拦截请求执行,错误未被正确捕获返回,导致200类的成功响应通过了状态码断言。

3. 测试数据存储位置确认

因为没有触发测试库创建流程,测试运行中写入的所有Snippet数据,都会永久保存在原有loc_db库的snippet_snippet表中,直接查询该表即可定位到所有测试残留数据。

修复方案
  • 第一步:补全pytest-django基础配置
    • 安装依赖:pip install pytest-django
    • 执行pytest --version确认插件加载状态,输出的插件列表中需要存在django项。
    • 插件正常加载后,第一次产生数据库连接时,会自动按照Django规则创建test_loc_db测试库,执行过程中会在控制台打印Creating test database for alias 'default'...的日志。
  • 第二步:修正批量序列化逻辑
    去掉重复写入的冗余代码,简化批量创建流程:
    class BulkUpdateOrCreateListSerializer(serializers.ListSerializer):
        def create(self, validated_data):
            try:
                # 直接构造未持久化的模型实例,一次性批量插入
                instances = [self.child.Meta.model(**attrs) for attrs in validated_data]
                return self.child.Meta.model.objects.bulk_create(instances)
            except IntegrityError as e:
                raise ValidationError(e)
    
    class SnippetSerializer(serializers.ModelSerializer):
        class Meta:
            model = Snippet
            fields = ['id','title', 'code', 'linenos']
            read_only_fields = ['id']
            list_serializer_class = BulkUpdateOrCreateListSerializer
    
  • 第三步:验证测试隔离效果
    可在测试用例中加入临时校验逻辑,确认当前使用的是独立测试库而非原业务库:
    from django.db import connection
    
    @pytest.mark.django_db
    def test_update_snippet(factory, snippets):
        # 临时验证数据库连接目标
        assert connection.settings_dict['NAME'] == 'test_loc_db'
        request = factory.post('/add-snippets/', snippets)
        view = SnippetUpdateView.as_view()
        response = view(request)
        response.render()
        assert status.is_success(response.status_code)
    
    测试执行完成后,pytest-django会自动销毁测试库,不会在原业务库中残留测试数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.02 10:54:07