使用ImageField的Django测试模型

Fab*_*o A 38 python testing django mocking

我需要测试我的Django应用程序的Photo模型.如何使用测试图像文件模拟ImageField?

tests.py

class PhotoTestCase(TestCase):

    def test_add_photo(self):
        newPhoto = Photo()
        newPhoto.image = # ??????
        newPhoto.save()
        self.assertEqual(Photo.objects.count(), 1)
Run Code Online (Sandbox Code Playgroud)

Fab*_*o A 66

对于未来的用户,我已经解决了这个问题.您可以使用SimpleUploadedFile实例模拟ImageField.

test.py

from django.core.files.uploadedfile import SimpleUploadedFile

newPhoto.image = SimpleUploadedFile(name='test_image.jpg', content=open(image_path, 'rb').read(), content_type='image/jpeg')
Run Code Online (Sandbox Code Playgroud)

  • 你能告诉我`image_path`是什么? (14认同)
  • 这种方法有效,但每次我运行测试时,都会在 /media 目录中创建新的图像文件。 (3认同)
  • 完美,应该是公认的答案。适用于 1.10,谢谢! (2认同)
  • @Norak 通过一些实验,我发现 `name` 是您要用于读取图像的文件名,而 `image_path` 是图像的路径。例如`/path/to/image.jpg`。 (2认同)
  • 您可以为内容设置二进制吗?`content=b"some content"` 这样您就不必仅仅为了测试而拥有实际图像? (2认同)

Chi*_*and 18

告诉模拟库基于Django的File类创建一个模拟对象

import mock
from django.core.files import File

file_mock = mock.MagicMock(spec=File, name='FileMock')
Run Code Online (Sandbox Code Playgroud)

然后在你的测试中使用

newPhoto.image = file_mock
Run Code Online (Sandbox Code Playgroud)

  • Mock现在是Python> = 3.3的标准python库,所以不要把这个第三方库视为Python中的奇怪东西. (8认同)

小智 13

您可以使用临时文件tempfile.因此,您不需要真正的文件来进行测试.

import tempfile

image = tempfile.NamedTemporaryFile(suffix=".jpg").name
Run Code Online (Sandbox Code Playgroud)

如果您更喜欢手动清理,请tempfile.mkstemp()改用.


Max*_*lov 8

解:

from StringIO import StringIO
# in python 3: from io import StringIO
from PIL import Image
from django.core.files.base import File
Run Code Online (Sandbox Code Playgroud)

并在TestCase类中创建一个静态方法:

@staticmethod
def get_image_file(name='test.png', ext='png', size=(50, 50), color=(256, 0, 0)):
    file_obj = StringIO()
    image = Image.new("RGBA", size=size, color=color)
    image.save(file_obj, ext)
    file_obj.seek(0)
    return File(file_obj, name=name)
Run Code Online (Sandbox Code Playgroud)

例:

instance = YourModel(name=value, image=self.get_image_file())
Run Code Online (Sandbox Code Playgroud)

  • 对于 Python 3,我认为 `from io import BytesIO` 而不是 `StringIO` (6认同)

Fli*_*imm 7

如果您不想在文件系统中创建实际文件,则可以改用此37字节的GIF,它足够小,可以在代码中成为字节文字:

from django.core.files.uploadedfile import SimpleUploadedFile

small_gif = (
    b'\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x00\x00\x00\x21\xf9\x04'
    b'\x01\x0a\x00\x01\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02'
    b'\x02\x4c\x01\x00\x3b'
)
uploaded = SimpleUploadedFile('small.gif', small_gif, content_type='image/gif')
Run Code Online (Sandbox Code Playgroud)

  • 这会产生一个白色像素。我发现了另一个 gif,甚至更小(只有 35 字节),它产生一个黑色像素。如果有人感兴趣的话,它是: `b'\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\x05\x04\x04\x00\x00\x00\ x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3b'` (4认同)