3

I'm designing a Django test in which I upload an .xml file. If the file is correct (validated by the schema) it's data it's added to project's database.

Part of the code for the view:

if request.method == 'POST':
    form = UploadFileForm(request.POST, request.FILES)
    if form.is_valid():
        result = parse_xml_question(request.FILES['docfile'], topic_id)

I have the following class for the form:

class UploadFileForm(forms.Form):
    docfile = forms.FileField(
        label='Select a file',
        help_text='.xml file'
    )

The html where the form is used:

<form action="{% url 'add_question_w_subject_topic' subject.id topic.id %}" enctype="multipart/form-data" method="post">
    {% csrf_token %}
    <p>{{ form.non_field_errors }}</p>
    <p>{{ form.docfile.label_tag }}</p>
    <p>
        {{ form.docfile.errors }}
        {{ form.docfile }}
    </p>
    <p><input type="submit" value="Upload" /></p>
</form>

And the test that fails:

def test_question_file_wrong_format(self):
    c = Client()

    script_dir = os.path.dirname(__file__)
    rel_path = "xml_files/wrong_format.xml"
    abs_file_path = os.path.join(script_dir, rel_path)

    response = c.post('/add/question/'+ str(self.subj1.id) +'/'
        + str(self.topc1.id) + '/', {'docfile': 
        open(abs_file_path, 'rb')})
    self.assertEquals(response.status_code, 200)

Notice this line:

response = c.post('/add/question/'+ str(self.subj1.id) +'/'
            + str(self.topc1.id) + '/', {'docfile': 
            open(abs_file_path, 'rb')})

I have tried several ways. In all of them, it returns a status code 302, while I was expecting 200,

I've read this, and I can't understand it enough to adapt that solution to my code.

If you need more information, just tell me. Sorry if it's an already answered question.

Any help or hint will be greatly appreciated. Thanks!

Community
  • 1
  • 1

1 Answers1

3

I have done this slightly differently in the past, using a file generated in the test case, without touching the filesystem:

    fake_file = ContentFile(b"Some file content")
    fake_file.name = 'myfile.xml'

    post_data = {
        'title': "Test document",
        'file': fake_file,
    }
    url = '/add/question/'+ str(self.subj1.id) +'/' + str(self.topc1.id) + '/'
    response = self.client.post(url, post_data)

Failing that, it's important that you submit the form with content_type='multipart/form-data'. If you use self.client rather than Client then this is done automatically if you include a data argument. See https://docs.djangoproject.com/en/1.10/topics/testing/tools/#django.test.Client.post

nimasmi
  • 3,978
  • 1
  • 25
  • 41
  • Thank you I will check into it – Ignacio Tiraboschi Oct 30 '16 at 13:53
  • When I try this approach, I get a form validation error: AssertionError -------------------------------------------------------------- Captured stdout call ---------------------------------------------------------------
    • my_file
      • This field is required.
    – Derek Aug 27 '17 at 09:34
  • On the next line in the test case look at `response.context['form'].errors` to see what the cause might be. – nimasmi Aug 27 '17 at 11:59
  • @nimasmi Shouldn't that be `ContentFile(b"Some file content")`? – yofee Jan 22 '18 at 07:29
  • @yofee, ooh, yes. How on Earth did that happen? Brain not engaged, I guess. Corrected. Thanks very much. – nimasmi Jan 22 '18 at 11:02