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
相关产品推荐
相关产品推荐

