Django使用测试夹具测试FileField

stt*_*ter 24 python django unit-testing django-testing filefield

我正在尝试为一些具有FileField的模型构建测试.该模型如下所示:

class SolutionFile(models.Model):
    '''
    A file from a solution.
    '''
    solution = models.ForeignKey(Solution)
    file = models.FileField(upload_to=make_solution_file_path)
Run Code Online (Sandbox Code Playgroud)

我遇到了两个问题:

  1. 使用时将数据保存到夹具时./manage.py dumpdata,不保存文件内容,只将文件名保存到夹具中.虽然我发现这是预期的行为,因为文件内容没有保存到数据库中,我想以某种方式将这些信息包含在夹具中进行测试.

  2. 我有一个用于上传文件的测试用例,如下所示:

    def test_post_solution_file(self):
        import tempfile
        import os
        filename = tempfile.mkstemp()[1]
        f = open(filename, 'w')
        f.write('These are the file contents')
        f.close()
        f = open(filename, 'r')
        post_data = {'file': f}
        response = self.client.post(self.solution.get_absolute_url()+'add_solution_file/', post_data,
                                    follow=True)
        f.close()
        os.remove(filename)
        self.assertTemplateUsed(response, 'tests/solution_detail.html')
        self.assertContains(response, os.path.basename(filename))
    
    Run Code Online (Sandbox Code Playgroud)

虽然此测试工作正常,但在完成后将上传的文件保留在媒体目录中.当然,删除可以照顾tearDown(),但我想知道Django是否有另一种处理方式.

我想到的一个解决方案是使用不同的媒体文件夹进行测试,必须与测试夹具保持同步.有没有办法在settings.py运行测试时指定另一个媒体目录?我可以在dumpdata中包含某种钩子,以便同步媒体文件夹中的文件吗?

那么,是否有更多的Pythonic或Django特定方式处理涉及文件的单元测试?

wat*_*oof 23

Django提供了一种在FileFields上编写测试的好方法,而不会在真正的文件系统中乱码 - 使用SimpleUploadedFile.

from django.core.files.uploadedfile import SimpleUploadedFile

my_model.file_field = SimpleUploadedFile('best_file_eva.txt', b'these are the contents of the txt file')
Run Code Online (Sandbox Code Playgroud)

这是django的魔法特征之一 - 不要在文档中显示:).但是这里提到了它.

  • 非二进制内容在Python 3+中引发错误; 你可以通过简单地使内容二进制来解决这个问题,如下所示:`my_model.file_field = SimpleUploadedFile('best_file_eva.txt',b'these是文件内容!') (7认同)

小智 5

您可以MEDIA_ROOT使用@override_settings()装饰器覆盖测试设置,如下所示:

from django.test import override_settings


@override_settings(MEDIA_ROOT='/tmp/django_test')
def test_post_solution_file(self):
  # your code here
Run Code Online (Sandbox Code Playgroud)