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)
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')
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
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()
.
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())
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')
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""))
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)