Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to simulate filedata for testing a form?

I'm trying to test a self written FormField AudioFileFormField, which checks if a file is an audiofile before storing it. For that i have overwritten the to_python method. Trying to test this FormField i ran into some difficulties.

This is my TestCase so far:

from django import forms
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase

class TestAudioFileFormField(TestCase):
    """ test the formfield to use for AudioFile Uploads """

    class TestForm(forms.Form):
        audiofilefield = AudioFileFormField()


    def setUp(self):

        self.AUDIOFILE_TEST_ROOT = os.path.dirname(__file__) + '/data/'
        self.files = audiofile_files


    def test_to_python(self):
        """ assign some files to a form and validate the form """

        f = file(self.AUDIOFILE_TEST_ROOT + self.files[0]) 
        file_data = {'audiofilefield':SimpleUploadedFile( self.files[0],f.read() )}
        data = {}

        form = self.TestForm(data,f)
        form.is_valid()

The line form.is_valid() raises an AttributeError: 'file' object has no attribute 'get'

When i insert a debug trace right before form.is_valid(), this is what i get in that interactive session:

ipdb> form.is_valid()
AttributeError: 'file' object has no attribute 'get'
ipdb> suf = file_data['audiofilefield']
ipdb> suf
<SimpleUploadedFile: invalid_format.mp3 (text/plain)>
ipdb> dir(suf)
[lots of info here]
ipdb> form.is_valid()
True

What exactly did i change in the interactive session, so that the form validation is working? What would be the correct way to pass the file to SimpleUploadedFile to avoid the AttributeError?

like image 423
marue Avatar asked Apr 24 '12 08:04

marue


2 Answers

Ok, a fresh look can be worth a lot. This is my new test_to_python test, this time it works:

def test_to_python(self):
    f = file(self.AUDIOFILE_TEST_ROOT + self.files[0])
    file_data = {'audiofilefield':SimpleUploadedFile(self.files[0],f.read())}
    data = {}
    form = self.TestForm(data,file_data)
    self.assertTrue( form.is_valid() )
like image 130
marue Avatar answered Nov 15 '22 10:11

marue


Alternative solution (because this question is the top Google result for "Django test simulate upload"): Django's builtin test client accepts open file objects as POST data:

# the form
class TestForm(forms.Form):
    audiofilefield = AudioFileFormField()

# the view
def upload_view(request):
    form = TestForm(data=request.POST or None, files=request.FILES or None)
    if request.method == 'POST':
         if form.is_valid():
              return HttpResponse('success')
         else:
              return HttpResponse('fail')

# the test function
class UploadTest(TestCase):
    def test_upload(self):
        c = Client() # django.test.client.Client
        formdata = {}
        with open('/my/audiofile.mp3', 'rb') as f:
            formdata['audiofilefield'] = f
            response = c.post('/my-test-view/', formdata)
like image 36
chrisv Avatar answered Nov 15 '22 11:11

chrisv