Unit Testing a Django Form with a FileField
The accepted answer has a downside, i.e. you always have to keep a dummy file in you environment for testing.
Assuming you are working in a team or in production, that is not very good practice. @xyres approach seems cleaner to me. It can be simplified more though.
As Python3 io docks mention, you can do something like:
loaded_file = BytesIO(b"some dummy bcode data: \x00\x01")
loaded_file.name = 'test_file_name.xls'
# and to load it in form
file_dict = {'file': SimpleUploadedFile(loaded_file.name, loaded_file.read())}
Full version
# Python3
from io import BytesIO
from django.core.files.uploadedfile import SimpleUploadedFile
class FormTestCase(TestCase)
def test_form(self):
# Simple and Clear
loaded_file = BytesIO(b"some dummy bcode data: \x00\x01")
loaded_file.name = 'test_file_name.xls'
post_dict = {'title': 'Test Title'}
file_dict = {'file': SimpleUploadedFile(loaded_file.name, loaded_file.read())}
form = MyForm(post_dict, file_dict)
self.assertTrue(form.is_valid())
It is also advised to utilize setUpTestData(cls)
and setUp(self)
class methods for data preparation.
I personally found Mozilla's intro to unit testing very informative and straightforward.
So far I have found this way that works
from django.core.files.uploadedfile import SimpleUploadedFile
...
def test_form(self):
upload_file = open('path/to/file', 'rb')
post_dict = {'title': 'Test Title'}
file_dict = {'file': SimpleUploadedFile(upload_file.name, upload_file.read())}
form = MyForm(post_dict, file_dict)
self.assertTrue(form.is_valid())
May be this is not quite correct, but I'm creating image file in unit test using StringIO:
imgfile = StringIO('GIF87a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00ccc,\x00'
'\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;')
imgfile.name = 'test_img_file.gif'
response = self.client.post(url, {'file': imgfile})
Here's another way that doesn't require you to use an actual image.
EDIT: Updated for Python 3.
from PIL import Image
from io import BytesIO # Python 2: from StringIO import StringIO
from django.core.files.uploadedfile import InMemoryUploadedFile
...
def test_form(self):
im = Image.new(mode='RGB', size=(200, 200)) # create a new image using PIL
im_io = BytesIO() # a BytesIO object for saving image
im.save(im_io, 'JPEG') # save the image to im_io
im_io.seek(0) # seek to the beginning
image = InMemoryUploadedFile(
im_io, None, 'random-name.jpg', 'image/jpeg', len(im_io.getvalue()), None
)
post_dict = {'title': 'Test Title'}
file_dict = {'picture': image}
form = MyForm(data=post_dict, files=file_dict)