Testing File uploads in Flask

I was recently writing Flask integration tests for a form that had a file upload parameter. As it turns out, is isn't as straight forward as I had thought it would be.

A basic file upload test might look like this:

def test_logo(self):  
   data = dict(logo=(io.BytesIO(b'test'), 'test_file.jpg')
   response = self.client.post(
       url_for('items.save'), data=data,
       follow_redirects=True,
       content_type='multipart/form-data'
   )
   self.assertIn(b'Your Item has been saved.', response.data)
   item = Item.query.get(1)
   self.assertIsNotNone(item.logo)

And that all work fine. The two key things to remember are that (in Python 3) your 'file' (in this case 'logo') needs to be a Bytes object and you need to add the content_type='multipart/form-data' param.

Where I ran into trouble though was that I was uploading more than just the logo. In fact for the form to validate it needed a lot of other fields present.

So when I tried it again with all the required fields as part of the data dict I got a strange error: TypeError: 'str' does not support the buffer interface.

As it turns out, there were non-string values in the data dict I was passing though which, when combined with the content_type caused this issue.

So to be able to run the test I had to ensure that all the fields were strings. So I simply looked over the data dict and made all the fields strings:

def test_edit_logo(self):  
    # get test data dictionary
    data = self.get_edit_data()
    for key, value in data.items():
        if not isinstance(value, str):
            data[key] = str(value)
    data['logo'] = (io.BytesIO(b'test'), 'test_file.jpg')
    response = self.client.post(
        url_for('items.save'), data=data, follow_redirects=True,
        content_type='multipart/form-data'
    )
    self.assertIn(b'Your Item has been saved.', response.data)
        item = Item.query.get(1)
        self.assertIsNotNone(item.logo)

And that's it. It's a simple modification that needs to be made but the error isn't very helpful when it comes to debugging.