Python:如何在我的测试套件中制作临时文件?

时间:2010-11-16 22:27:03

标签: python unit-testing testing temporary-files

(我正在使用Python 2.6和nose。)

我正在为我的Python应用程序编写测试。我想要一个测试打开一个新文件,关闭它,然后删除它。当然,我更喜欢这会发生在临时目录中,因为我不想丢弃用户的文件系统。而且,它需要跨OS。

我该怎么做?

6 个答案:

答案 0 :(得分:26)

使用py.test的FWIW你可以写:

def test_function(tmpdir):
    # tmpdir is a unique-per-test-function invocation temporary directory

使用“tmpdir”函数参数的每个测试函数将获得一个干净的空目录,创建为“/ tmp / pytest-NUM”的子目录(linux,win32具有不同的路径),其中每次测试运行都会增加NUM 。保留最后三个目录以便于检查,并自动删除旧的目录。您还可以使用py.test --basetemp=mytmpdir设置基本临时目录。

tmpdir对象是一个py.path.local对象,它也可以像这样使用:

sub = tmpdir.mkdir("sub")
sub.join("testfile.txt").write("content")

但将它转换为“字符串”路径也很好:

tmpdir = str(tmpdir)

答案 1 :(得分:15)

请参阅标准库中的tempfile模块 - 应该是您所需要的。

答案 2 :(得分:4)

我没有直接使用tempfile,而是建议使用上下文管理器包装器 - 上下文管理器负责在所有情况下(成功/失败/异常)删除目录,基本上没有样板。

以下是它的使用方法:

from tempdir import TempDir
...

# in some test:
with TempDir() as d:
    temp_file_name = os.path.join(d.name, 'your_temp_file.name')
    # create file...
    # ...
    # asserts...

我一直在使用自己开发的版本(实现相当短 - 在20行以下),当我需要在其他地方使用它的时候,所以我环顾四周是否有一个包准备好安装,确实有:tempdir

答案 3 :(得分:1)

Python 3.2 +

tempfile library TemporaryDirectory() 与上下文管理器with 齐头并进。但是,请注意,这实际上是创建临时目录(在临时文件的某些OS目录中(在Linux上可能是/tmp))-那里的文件实际上将使用存储设备/磁盘-对于你,但是这是什么时候需要考虑的事情,例如付费服务((有关替代方法,请参见此答案的结尾)

我还建议使用os library os.path.join()来放置内容并一般使用,以避免与\/路径有关的跨平台错误。 / p>

注意:在没有上下文管理器with的情况下使用时,您将获得TemporaryDirectory类的对象 并使用.name检索名称 ,在上下文管理器中使用时,您会得到分配给您的as变量的名称 string

TL; DR:代码

import tempfile
import os
with tempfile.TemporaryDirectory() as tempdir:
  # you can e.g. create a file here:
  tmpfilepath = os.path.join(tempdir, 'someFileInTmpDir.txt')
  with open(tmpfilepath, 'w') as tmpfile:
    tmpfile.write("something")

更改临时目录位置

在这里您必须进行更深入的研究,因为documentation在这里有点模糊:它根本不记录其参数,但会将您发送到mkdtemp(),后者应使用相同的规则,并且在那里,它会将您发送到mkstemp(),在这里您最终可以确保自己使用dir参数来覆盖默认目录位置。

您要完全伪造文件系统上的I / O(输入/输出)操作吗?

您可以按照此答案的建议尝试使用pyfakefshttps://stackoverflow.com/a/46817032/1835470

哪个更好?伪造文件系统还是物理临时目录?

取决于使用情况-通常结合使用可能是一个不错的折衷方案-使用真实目录和文件自己测试每个文件系统操作,以便您知道它确实有效,但是对于自定义的大量使用的东西,请使用伪造/模拟文件系统操作:)例如,还用于测试来自OS内部的权限-最好使用物理方式。
您必须始终预先评估可提供的性能和耐用性以及是否需要进行额外的测试。

答案 4 :(得分:0)

要为测试创建具有自定义内容的临时文件,可以使用此类:

import os, tempfile

class TestFileContent:                                                                                                  
    def __init__(self, content):                                                                                        

        self.file = tempfile.NamedTemporaryFile(mode='w', delete=False)                                                 

        with self.file as f:                                                                                            
            f.write(content)                                                                                            

    @property                                                                                                           
    def filename(self):                                                                                                 
        return self.file.name                                                                                           

    def __enter__(self):                                                                                                
        return self                                                                                                     

    def __exit__(self, type, value, traceback):                                                                         
        os.unlink(self.filename)                                                                                        

此类将创建一个临时文件,在其中写入您的内容,然后关闭该文件。 您可以在with语句中使用它,以确保在使用这种文件后将其删除:

    with TestFileContent(
'''Hello, world
'''
    ) as test_file:

        # Here, a temporary file has been created in the file named test_file.filename with the specified content
        # This file will be deleted once you leave the with block

答案 5 :(得分:0)

对于将来遇到这种情况但又由于某些原因而拒绝使用pytest的人:

我写了tempcase,这是一个小型库,它为unittest.TestCase子类提供了方便的方法来处理临时目录。在您请求目录路径之前,不会创建任何目录,并且目录已在项目,TestCase类,时间戳和测试方法中命名。它们将在之后自动清理。您可以通过设置属性来禁用清理功能以检查输出。

如果您正在逐步移植代码,那么还有一个装饰器可以应用于单个测试用例。