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

Django中使用factory_boy生成的测试文件无法自动删除的问题

解决factory_boy生成测试文件无法自动删除的问题

问题描述

我在使用factory_boy生成测试用随机数据时,每次测试结束后,生成的文件无法自动删除,请问需要添加什么配置或代码来解决这个问题?

提供的代码片段

测试用工厂类

class TrackFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = "tracks.Track"

    id = factory.Faker("uuid4")
    filename = "Track 01 - track"
    created_by = factory.SubFactory(UserFactory)
    file = factory.django.FileField(filename="test.mp3")
    track_length = 145

    @classmethod
    def _create(cls, model_class, *args, **kwargs):
        instance = cls.build(*args, **kwargs)
        instance.save()
        return instance

测试用例

class TestViewDeleteTrack(AuthorizedApiTestCase):
    def setUp(self):
        self.url = reverse('list-track')
        self.user_data = UserFactory()
        self.data = TrackFactory(created_by=self.user_data)
        self.client.force_authenticate(user=self.user_data)

    def test_list_tracks(self):
        self.get_and_assert_equal_status_code(status.HTTP_200_OK)

    def test_delete_track_valid_pk(self):
        self.delete_and_assert_equal_status_code(
            "delete-track",
            self.data.pk,
            status.HTTP_204_NO_CONTENT,
        )

自定义测试方法

def get_and_assert_equal_status_code(self, status_code):
        response = self.client.get(self.url)
        self.assertEqual(response.status_code, status_code)
        return response

def delete_and_assert_equal_status_code(self, url_name, pk, status_code):
        url = reverse(url_name, kwargs={"pk": pk})
        response = self.client.delete(url)
        self.assertEqual(response.status_code, status_code)

解决方案

1. 用临时文件生成测试文件

修改工厂类中的file字段,使用临时文件而非固定文件名,后续清理更便捷:

import tempfile
from django.core.files.base import ContentFile

class TrackFactory(factory.django.DjangoModelFactory):
    # 其他字段保持不变
    file = factory.django.FileField(
        filename="test.mp3",
        from_func=lambda: ContentFile(
            tempfile.NamedTemporaryFile(suffix=".mp3").read(),
            name="test.mp3"
        )
    )

2. 在测试用例的tearDown中手动清理文件

测试结束后,无论成功失败,手动删除生成的文件:

import os

class TestViewDeleteTrack(AuthorizedApiTestCase):
    # setUp和测试方法保持不变

    def tearDown(self):
        # 检查文件存在后删除
        if self.data.file and self.data.file.path:
            try:
                os.remove(self.data.file.path)
            except FileNotFoundError:
                pass
        super().tearDown()

3. 用override_settings设置临时媒体目录

通过Django的装饰器将测试时的MEDIA_ROOT设为临时目录,测试结束后整个目录会被自动清理:

import tempfile
from django.test import override_settings

@override_settings(MEDIA_ROOT=tempfile.mkdtemp())
class TestViewDeleteTrack(AuthorizedApiTestCase):
    # 测试代码保持不变

4. 修复工厂类的_create方法(可选)

自定义的_create方法可能跳过了factory_boy的内置清理逻辑,可改为调用父类实现:

@classmethod
def _create(cls, model_class, *args, **kwargs):
    return super()._create(model_class, *args, **kwargs)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 05:46:05