Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing file uploads in Flask

Tags:

python

flask

I'm using Flask-Testing for my Flask integration tests. I've got a form that has a file upload for a logo that I'm trying to write tests for but I keep getting an error saying: TypeError: 'str' does not support the buffer interface.

I'm using Python 3. The closest answer I have found is this but it's not working for me.

This is what one of my many attempts looks like:

def test_edit_logo(self):     """Test can upload logo."""     data = {'name': 'this is a name', 'age': 12}     data['file'] = (io.BytesIO(b"abcdef"), 'test.jpg')     self.login()     response = self.client.post(         url_for('items.save'), data=data, follow_redirects=True)     })     self.assertIn(b'Your item has been saved.', response.data)     advert = Advert.query.get(1)     self.assertIsNotNone(item.logo) 

How does one test a file upload in Flask?

like image 908
hammygoonan Avatar asked Feb 28 '16 15:02

hammygoonan


People also ask

How do you handle file uploads in Flask?

Handling file upload in Flask is very easy. It needs an HTML form with its enctype attribute set to 'multipart/form-data', posting the file to a URL. The URL handler fetches file from request. files[] object and saves it to the desired location.


2 Answers

The issue ended up not being that when one adds content_type='multipart/form-data' to the post method it expect all values in data to either be files or strings. There were integers in my data dict which I realised thanks to this comment.

So the end solution ended up looking like this:

def test_edit_logo(self):     """Test can upload logo."""     data = {'name': 'this is a name', 'age': 12}     data = {key: str(value) for key, value in data.items()}     data['file'] = (io.BytesIO(b"abcdef"), 'test.jpg')     self.login()     response = self.client.post(         url_for('adverts.save'), data=data, follow_redirects=True,         content_type='multipart/form-data'     )     self.assertIn(b'Your item has been saved.', response.data)     advert = Item.query.get(1)     self.assertIsNotNone(item.logo) 
like image 147
hammygoonan Avatar answered Oct 08 '22 22:10

hammygoonan


You need two things:

1.) content_type='multipart/form-data' in your .post()
2.) in your data= pass in file=(BytesIO(b'my file contents'), "file_name.jpg")

A full example:

    data = dict(         file=(BytesIO(b'my file contents'), "work_order.123"),     )      response = app.post(url_for('items.save'), content_type='multipart/form-data', data=data) 
like image 30
mmcclannahan Avatar answered Oct 08 '22 23:10

mmcclannahan