Python django中UnitTestFileField的干净方法是什么?

Python django中UnitTestFileField的干净方法是什么?,python,django,filefield,django-unittest,Python,Django,Filefield,Django Unittest,我有一个带有文件字段的模型。我想测试一下。django测试框架有很好的方法来管理数据库和电子邮件。文件字段是否有类似的功能 如何确保单元测试不会污染实际应用程序 提前谢谢 附言:我的问题几乎是重复的,但它没有一个公认的答案。我只想再问一下这个主题是否有新的内容。我通常使用doctest测试模型中的文件字段 >>> from django.core.files import File >>> s = SimpleModel() >>> s.au

我有一个带有文件字段的模型。我想测试一下。django测试框架有很好的方法来管理数据库和电子邮件。文件字段是否有类似的功能

如何确保单元测试不会污染实际应用程序

提前谢谢


附言:我的问题几乎是重复的,但它没有一个公认的答案。我只想再问一下这个主题是否有新的内容。

我通常使用doctest测试模型中的文件字段

>>> from django.core.files import File
>>> s = SimpleModel()
>>> s.audio_file = File(open("media/testfiles/testaudio.wav"))
>>> s.save()
>>> ...
>>> s.delete()
如果需要,我还可以使用测试客户端测试文件上传

至于fixture,在修改fixture中的路径后,我只需将所需的文件复制到测试文件夹中

e、 g

在包含文件场指向名为“audio”的目录的模型的夹具中,将“audio”:“audio/audio.wav”替换为“audio”:“audio/test/audio.wav”。
现在,您所要做的就是将测试文件夹和必要的文件复制到测试设置的“音频”中,然后在拆卸中删除它


这不是我所认为的最干净的方法,但我就是这么做的。

有几种方法可以解决这个问题,但它们都很难看,因为单元测试应该是隔离的,但文件都是持久的更改

我的单元测试不是在有生产数据的系统上运行的,因此每次运行后都可以简单地用类似于
git reset--hard
的方法重置上传目录。这种方法在某些方面是最好的,因为它不涉及代码更改,并且只要您从良好的测试数据开始,它就可以保证工作

如果在测试了模型的保存方法之后,您实际上不需要对该文件做任何事情,我建议使用python的优秀工具来完全伪造
文件
实例(即类似
mock\u file=mock(spec=django.core.files.file);mock\u file.read.return\u value=“fake file contents”
)因此,您可以完全避免更改文件处理逻辑。Mock库有两种方法可以在测试方法中访问Django,这与本文得到的方法一样简单

如果您需要一个真实的文件(即用作测试的一部分、使用外部脚本处理等),您可以使用类似于Mirko示例的方法,并在确保将其存储在适当的位置后创建一个文件-以下是三种方法:

  • 让您的测试
    设置。MEDIA\u ROOT
    指向一个临时目录(请参阅Python模块的
    mkdtemp
    函数)。只要您有一个单独的
    STATIC\u ROOT
    之类的东西,它就可以正常工作,您可以将它用于作为源代码一部分的媒体文件
  • 使用自定义
  • 在每个文件实例上手动设置文件路径,或使用自定义函数指向测试设置/拆卸过程清除的某个位置,例如
    MEDIA\u ROOT
    下的测试子目录

编辑:模拟对象库在python 3.3版中是新的。对于较旧的python版本,请选中

如果您只想创建一个需要文件字段的对象,而不想使用此字段,则可以像下面这样传递任何(现有或不存在)相对路径:

example_object = models.ExampleModel({'file': "foo.bar"})
example_object.save()

然后它就可以使用了。

Django提供了一个很好的方法来实现这一点——使用
SimpleUploadedFile
临时上传文件<如果只需要存储一些sentinel数据,则代码>SimpleUploadedFile
通常是更简单的选项:

from django.core.files.uploadedfile import SimpleUploadedFile

my_model.file_field = SimpleUploadedFile(
    "best_file_eva.txt",
    b"these are the file contents!"   # note the b in front of the string [bytes]
)
这是django的神奇功能之一,在文档中不会出现:)。然而,它被引用并实施

局限性 请注意,您只能将
字节
放入
SimpleUploadedFile
中,因为它是在幕后使用
字节
实现的。如果您需要更真实的、类似文件的行为,您可以使用
临时上传文件

对于Python 2 如果您仍停留在python 2上,请跳过内容中的
b
前缀:

my\u model.file\u field=SimpleUploadedFile(
“最佳文件\u eva.txt”,
“这些是文件内容!”#否b
)

我想最简单的方法是使用ContentFile类:

file = ContentFile('text', 'name')
my_model = MyModel()
my_model.file = file
my_model.save()

谢谢你的回答。最后,通过在测试用例设置中更改此变量的值,我选择指向一个单元测试媒体\u根。mock现在是Python标准库的一部分,在Python 3.3以后的版本中作为unittest.mock提供—从REAME收集。rst@chachan你能建议编辑吗?这个答案肯定需要更新我不知道。谢谢你的评论。我将对此进行研究,内容必须是Python2.x中的str()和Python3.x中的bytes()。你不能把文本/unicode放在那里。我知道4年后我会问这个问题,但是。。。有没有办法伪造文件大小?@pta2002这听起来像是一个单独的问题:)这可能取决于你以后如何使用文件大小,所以在你打开新问题时,请包括这一点,这对我来说很有效,但文件保存在磁盘上,而我不想要。我通过模仿本文中所述的文件存储后端解决了这个问题。是否需要手动关闭文件句柄以释放它所使用的资源?