在django中单元测试FileField的干净方法是什么?

luc*_*luc 50 python django filefield django-unittest

我有一个带有FileField的模型.我想对它进行单元测试.django测试框架有很好的方法来管理数据库和电子邮件.FileFields有类似的东西吗?

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

提前致谢

PS:我的问题几乎是使用测试装置Django测试FileField的副本,但它没有接受的答案.只想重新询问这个话题是否有新内容.

wat*_*oof 85

Django提供了一种很好的方法 - 使用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]
)
Run Code Online (Sandbox Code Playgroud)

这是django的魔法特征之一 - 不要在文档中显示:).但是这里提到了它.

  • 内容*必须是Python 2.x中的str()和Python 3.x中的bytes().你不能在那里放置text/unicode. (7认同)
  • 这对我有用,但文件被保存在我不想要的磁盘上。我通过模拟文件存储后端解决了这个问题,如本文所述 https://csheng.info/2018/08/21/mocking-a-file-storage-backend-in-django-tests.html (3认同)
  • 我知道四年后我要问这个问题,但是...有没有办法伪造文件大小? (2认同)

Chr*_*ams 41

有几种方法可以解决这个问题,但它们都很丑陋,因为单元测试应该是隔离的,但文件都是关于持久的变化.

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

如果你在测试模型的save方法之后实际上不需要对该文件做任何事情,我建议使用python的优秀Mock库来完全伪造File实例(例如类似的东西mock_file = Mock(spec=django.core.files.File); mock_file.read.return_value = "fake file contents"),这样你就可以完全避免对文件处理逻辑的更改.Mock库有两种方法可以在一个测试方法中全局修补 Django的File类,这个方法就像这样容易.

如果你需要一个真实的文件(即用作测试的一部分,使用外部脚本进行处理等),你可以使用类似于Mirko的例子,并在确保它存储在适当的地方之后创建一个File对象. - 这有三种方法:

  • 让您的测试settings.MEDIA_ROOT指向临时目录(请参阅Python tempfile模块的mkdtemp功能).只要你有一些单独的东西STATIC_ROOT,你可以使用它作为源代码的一部分的媒体文件,这种方法很好.
  • 使用自定义存储管理器
  • 在每个File实例上手动设置文件路径,或者使用自定义upload_to函数指向您的测试设置/拆除过程清除的位置,例如下面的test子目录MEDIA_ROOT.

编辑:模拟对象库是python版本3.3中的新功能.对于较旧的python版本,请查看Michael Foord的版本

  • mock 现在是 Python 标准库的一部分,在 Python 3.3 以后的版本中作为 unittest.mock 可用 - 从 REAME.rst 收集 (2认同)

Mir*_*ini 13

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

>>> from django.core.files import File
>>> s = SimpleModel()
>>> s.audio_file = File(open("media/testfiles/testaudio.wav"))
>>> s.save()
>>> ...
>>> s.delete()
Run Code Online (Sandbox Code Playgroud)

如果我需要,我还测试文件上传与测试客户端.

至于灯具,我只需在修改灯具中的路径后,将我需要的文件复制到测试文件夹中.

例如

在包含指向名为"audio"的目录的文件脚本的模型中,将"audio":"audio/audio.wav"替换为"audio":"audio/test/audio.wav".
现在,您所要做的就是将测试文件夹和必要的文件复制到测试setUp中的"audio"中,然后在tearDown中将其删除.

不是我认为最干净的方式,但这就是我所做的.