如何在django中unit testingfile upload
在我的Django应用程序中,我有一个完成file upload的视图。核心片段就是这样的
... if (request.method == 'POST'): if request.FILES.has_key('file'): file = request.FILES['file'] with open(settings.destfolder+'/%s' % file.name, 'wb+') as dest: for chunk in file.chunks(): dest.write(chunk)
我想unit testing的观点。我打算testing愉快的path以及失败的path..其中request.FILES
没有关键'文件'的情况下, request.FILES['file']
有None
..
如何设置快乐path的发布数据?有人可以告诉我吗?
来自Client.post
上的Django文档:
提交文件是一个特例。 要发布文件,只需要提供文件字段名称作为密钥,并将文件句柄提供给要上载的文件作为值。 例如:
c = Client() with open('wishlist.doc') as fp: c.post('/customers/wishes/', {'name': 'fred', 'attachment': fp})
我以前with open('some_file.txt') as fp:
做同样的事情,但是之后我需要repo中的图片,video和其他真实文件,而且我正在testing一个经过很好testing的Django核心组件的一部分,所以目前这是我一直在做的事情:
from django.core.files.uploadedfile import SimpleUploadedFile def test_upload_video(self): video = SimpleUploadedFile("file.mp4", "file_content", content_type="video/mp4") self.client.post(reverse('app:some_view'), {'video': video}) # some important assertions ...
在Python 3.5+中,您需要使用bytes
对象而不是str
。 将"file_content"
更改为b"file_content"
它一直工作正常, SimpleUploadedFile
创build一个InMemoryFile
行为像一个常规的上传,你可以select名称,内容和内容types。
我build议你看看Django的RequestFactory 。 IT是模拟请求中提供的数据的最佳方法。
说,我发现你的代码有几个缺陷。
- “单位”testing意味着只testing一个function单位的“单位”。 所以,如果你想testing这个视图,你会testing视图和文件系统,而不是unit testing。 为了使这一点更清楚。 如果您运行该testing,并且视图正常工作,但您没有权限保存该文件,则testing将因此失败。
- 其他重要的是testing速度 。 如果你正在做TDD这样的testing,那么执行testing的速度就非常重要。 访问任何I / O不是一个好主意 。
所以,我build议你重构你的视图来使用如下的函数:
def upload_file_to_location(request, location=None): # Can use the default configured
并做一些嘲笑。 你可以使用Python模拟 。
PS:你也可以使用Django testing客户端但是这意味着你要添加更多的东西来testing,因为客户端使用会话,中间件等。没有类似的unit testing。
我为自己的事件相关的应用程序做这样的事情,但是你应该有足够多的代码来处理你自己的用例
import tempfile, csv, os class UploadPaperTest(TestCase): def generate_file(self): try: myfile = open('test.csv', 'wb') wr = csv.writer(myfile) wr.writerow(('Paper ID','Paper Title', 'Authors')) wr.writerow(('1','Title1', 'Author1')) wr.writerow(('2','Title2', 'Author2')) wr.writerow(('3','Title3', 'Author3')) finally: myfile.close() return myfile def setUp(self): self.user = create_fuser() self.profile = ProfileFactory(user=self.user) self.event = EventFactory() self.client = Client() self.module = ModuleFactory() self.event_module = EventModule.objects.get_or_create(event=self.event, module=self.module)[0] add_to_admin(self.event, self.user) def test_paper_upload(self): response = self.client.login(username=self.user.email, password='foz') self.assertTrue(response) myfile = self.generate_file() file_path = myfile.name f = open(file_path, "r") url = reverse('registration_upload_papers', args=[self.event.slug]) # post wrong data type post_data = {'uploaded_file': i} response = self.client.post(url, post_data) self.assertContains(response, 'File type is not supported.') post_data['uploaded_file'] = f response = self.client.post(url, post_data) import_file = SubmissionImportFile.objects.all()[0] self.assertEqual(SubmissionImportFile.objects.all().count(), 1) #self.assertEqual(import_file.uploaded_file.name, 'files/registration/{0}'.format(file_path)) os.remove(myfile.name) file_path = import_file.uploaded_file.path os.remove(file_path)
在Django 1.7中,TestCase有一个问题,可以通过使用open(filepath,'rb')来解决,但是当使用testing客户端时,我们无法控制它。 我认为最好确保file.read()总是返回字节。
来源: https ://code.djangoproject.com/ticket/23912,由KevinEtienne
没有rb选项,会引发TypeError:
TypeError: sequence item 4: expected bytes, bytearray, or an object with the buffer interface, str found
- 为django项目安装memcached
- ReactJS与Django – 真正的用法
- Django模型字段validation
- ValueError at / image / Tensor张量(“activation_5 / Softmax:0”,shape =(?,4),dtype = float32)不是该图的元素
- 如何使用Django获取当前的urlname?
- 如何访问Django模板中的用户configuration文件?
- 如何在models.py中引用django设置variables?
- Djangopipe理中的同一模型的多个ModelAdmins / views
- WordPress可以替代像Django或Ruby on Rails这样的框架