web-dev-qa-db-fra.com

Django modèle de test avec ImageField

J'ai besoin de tester le modèle Photo de mon application Django. Comment puis-je me moquer de l'ImageField avec un fichier image de test?

tests.py

class PhotoTestCase(TestCase):

    def test_add_photo(self):
        newPhoto = Photo()
        newPhoto.image = # ??????
        newPhoto.save()
        self.assertEqual(Photo.objects.count(), 1)
41
Fabrizio A

Pour les futurs utilisateurs, j'ai résolu le problème. Vous pouvez vous moquer d'un ImageField avec une instance SimpleUploadedFile.

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')
72
Fabrizio A

Dites à la bibliothèque fictive de créer un objet fictif basé sur la classe File de Django

import mock
from Django.core.files import File

file_mock = mock.MagicMock(spec=File, name='FileMock')

puis utiliser dans vos tests

newPhoto.image = file_mock
18
ChillarAnand

Vous pouvez utiliser un fichier temporaire, en utilisant tempfile . Vous n'avez donc pas besoin d'un vrai fichier pour faire vos tests.

import tempfile

image = tempfile.NamedTemporaryFile(suffix=".jpg").name

Si vous préférez effectuer un nettoyage manuel, utilisez plutôt tempfile.mkstemp().

16
Purpleweb.fr

Solution:

from StringIO import StringIO
# in python 3: from io import StringIO
from PIL import Image
from Django.core.files.base import File

Et créez une méthode statique dans votre classe 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)

Exemple:

instance = YourModel(name=value, image=self.get_image_file())
9
Maxim Panfilov

Si vous ne voulez pas créer un fichier réel dans le système de fichiers, vous pouvez utiliser ce GIF de 37 octets à la place, suffisamment petit pour être un littéral d'octets dans votre code:

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')
8
Flimm

Mon approche comment tester le modèle sans intention de transmettre des données utiles:

from Django.core.files import File
SomeModel.objects.create(image=File(file=b""))
1
Pavel Hanpari

Pour quelqu'un d'essayer le test de téléchargement d'image avec python 3.xx

Je corrige peu avec l'excellente réponse de Maxim Panfilov pour créer une image plus fictive avec un nom indépendant.

from io import BytesIO
from PIL import Image
from Django.core.files.base import File

#in your TestCase class:
class TestClass(TestCase):
    @staticmethod
    def get_image_file(name, ext='png', size=(50, 50), color=(256, 0, 0)):
        file_obj = BytesIO()
        image = Image.new("RGBA", size=size, color=color)
        image.save(file_obj, ext)
        file_obj.seek(0)
        return File(file_obj, name=name)

    def test_upload_image(self):
        c= APIClient()
        image1 = self.get_image('image.png')
        image2 = self.get_image('image2.png')
        data = 
            { 
                "image1": iamge1,
                "image2": image2,
            }
        response = c.post('/api_address/', data ) 
        self.assertEqual(response.status_code, 201) 
0
rumbarum