Question

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?

Was it helpful?

Solution

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() )

OTHER TIPS

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)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top