代码之家  ›  专栏  ›  技术社区  ›  luc

在django中,unittest FileField的干净方法是什么?

  •  44
  • luc  · 技术社区  · 15 年前

    我有一个带字段的模型。我想联合测试一下。django测试框架有很好的方法来管理数据库和电子邮件。文件域有类似的东西吗?

    如何确保单元测试不会污染实际应用程序?

    提前谢谢

    我的问题几乎是 Django test FileField using test fixtures 但它没有一个公认的答案。只是想再问一下这个话题有没有新的东西。

    4 回复  |  直到 9 年前
        1
  •  41
  •   chachan    8 年前

    有几种方法可以解决这个问题,但是它们都很难看,因为单元测试应该是独立的,但是文件都是关于持久的更改的。

    我的单元测试不在有生产数据的系统上运行,因此在每次运行之后,简单地重置upload目录是很容易的,比如 git reset --hard . 在某些方面,这种方法是最好的,因为它不涉及代码更改,而且只要您从良好的测试数据开始,它就可以保证工作。

    如果在测试了模型的save方法之后您实际上不需要对该文件做任何事情,我建议您使用python的 Mock library 完全伪造 File 实例(例如 mock_file = Mock(spec=django.core.files.File); mock_file.read.return_value = "fake file contents" )因此,您可以完全避免更改文件处理逻辑。模拟库有两种方法 globally patch Django's公司 File class 在一个测试方法中,这是最容易得到的。

    如果您需要一个真实的文件(例如,作为测试的一部分,使用外部脚本进行处理等),您可以使用类似于Mirko示例的东西,并创建一个 File object 在确保将其存储在适当的地方之后-有三种方法可以做到这一点:

    • 测试一下 settings.MEDIA_ROOT 指向一个临时目录(参见Python tempfile 模块的 mkdtemp 功能)。只要你有一个 STATIC_ROOT 用于作为源代码一部分的媒体文件。
    • 使用自定义 storage manager
    • 在每个文件实例上手动设置文件路径或具有自定义 upload_to 函数指向测试设置/拆卸进程清除的某个位置,例如 MEDIA_ROOT .

    编辑: 模拟对象库是python version 3.3中的新功能。对于较旧的python版本,请检查 Michael Foord's version

        2
  •  85
  •   waterproof    6 年前

    Django提供了一个很好的方法-使用SimpleUploadedFile。

    from django.core.files.uploadedfile import SimpleUploadedFile
    
    my_model.file_field = SimpleUploadedFile(
        "best_file_eva.txt",
        b"these are the file contents!"   # note the b in front of the string [bytes]
    )
    

    这是django的神奇功能之一,不会出现在文档中:)。但它是指 here .

    对于Python 2

    如果 你被python 2困住了,跳过 b 内容中的前缀:

    my_model.file_field = SimpleUploadedFile(
        "best_file_eva.txt",
        "these are the file contents!" # no b
    )
    
        3
  •  13
  •   Mirko Rossini    15 年前

    我通常使用doctest测试模型中的文件字段

    >>> from django.core.files import File
    >>> s = SimpleModel()
    >>> s.audio_file = File(open("media/testfiles/testaudio.wav"))
    >>> s.save()
    >>> ...
    >>> s.delete()
    

    如果需要,我还可以用测试客户机来测试上传的文件。

    对于fixture,在修改fixture中的路径之后,我只需将需要的文件复制到一个测试文件夹中。

    例如

    在包含指向名为“audio”目录的文件字段的模型的fixture中,将“audio”:“audio/audio.wav”替换为“audio”:“audio/test/audio.wav”。
    现在,您只需复制测试设置中“audio”中的测试文件夹和必要的文件,然后在tearDown中删除它。

    不是我想的最干净的方式,但我就是这么做的。

        4
  •  1
  •   Ctrl-C Shane Holloway    6 年前

    如果你只是想 创建对象 需要FileField和 不想使用此字段 然后,你可以通过任何(现有的或不存在的)相对路径,像这样:

    example_object = models.ExampleModel({'file': "foo.bar"})
    example_object.save()
    

    那就可以用了。