在 PyTest 中创建临时目录

47

我的Python项目可以顺利导入pytest 2.9.0,没有任何问题。

我想创建一个只在测试会话期间存在的新空目录。我发现pytest提供了临时目录支持:

https://pytest.org/latest/tmpdir.html

您可以使用tmpdir fixture来提供一个临时目录,该目录唯一于测试调用,在基本临时目录中创建。

tmpdir是一个py.path.local对象,它提供了os.path方法和更多功能。下面是一个示例测试用法:

pytest的源代码显示def tmpdir是全局/模块函数:https://pytest.org/latest/_modules/_pytest/tmpdir.html

但是,我的测试文件失败了:

import pytest

# ...

def test_foo():
    p = pytest.tmpdir()

出错信息:

AttributeError: 'module'对象没有'tmpdir'属性

使用from pytest import tmpdir导入失败,报错如下:

ImportError:无法导入名称tmpdir


4
文档中也列出了一些示例。 def test_foo(tmpdir) 这个函数对你是否有效? - vaultah
1
文档说明了如何使用它,而这个 SO 帖子也有一个例子。这对你有用吗? - idjaw
2个回答

78

更新: 使用tmp_path代替tmpdirtmp_path是一个pathlib.Path/pathlib2.Pathtmpdir是一个py.path(实际上是LocalPath),它提供了与pathlib.Path非常相似的语法。参见pytest问题反馈

开发人员不再推荐使用py.path。

语法类似,例如:

def test_something_else(tmp_path):
    #create a file "myfile" in "mydir" in temp directory
    f1 = tmp_path / "mydir/myfile"
    f1.parent.mkdir() #create a directory "mydir" in temp folder (which is the parent directory of "myfile"
    f1.touch() #create a file "myfile" in "mydir"


    #write to file as normal 
    f1.write_text("text to myfile")

    assert f1.read_text() == "text to myfile" 

翻译:我仔细研究了它,也发现了这种行为的特殊之处,并总结了下面我所学到的内容,供那些不太直观的人参考。

tmpdir是pytest中预定义的fixture,类似于此处定义的setup

import pytest

class TestSetup:
    def __init__(self):
        self.x = 4

@pytest.fixture()
def setup():
    return TestSetup()

def test_something(setup)
    assert setup.x == 4

因此,tmpdir是在pytest中定义的固定名称,如果您将其作为参数名称传递,则会传递给您的测试函数。

示例用法:

def test_something_else(tmpdir):
    #create a file handle for "myfile" in "mydir" in temp folder
    f1 = tmpdir.mkdir("mydir").join("myfile")

    #create a file handle for "myfile" in temp folder
    f2 = tmpdir.join("myfile")

    #write to file as normal (this is what actually creates the file)
    f1.write("text to myfile")

    assert f1.read() == "text to myfile"

当你使用pytest运行它时,它可以正常工作,例如在终端中运行py.test test_foo.py。以这种方式生成的文件具有读写访问权限,并且稍后可以在系统的临时文件夹中查看(对我来说,这是/tmp/pytest-of-myfolder/pytest-1/test_create_file0)。


3
感谢指出tmpdirtmp_path的区别,为此点赞。由于我以为tmpdir已经是一个pathlib.Path对象,所以一直收到一些奇怪的错误提示。 - jrieke
@Kuchara 很敏锐,你当然是对的。我已经编辑了答案。 - M.T
1
@M.T,你的更新代码中tmp_path应该等于什么?我们应该用想要创建临时文件的目录的字符串来替换它吗? - lightbox142
@lightbox142 tmp_path 的值将是一个随机生成的临时目录,类型为 pathlib.Path。您无需替换它,pytest 将检测参数名称(因为 pytest 具有具有该特定名称的 fixture,就像上面的示例中传递了 setup 参数一样),并在运行测试之前填充参数。 - M.T
1
@Jonas 你说得对,发现得很好。我会进行更正。 - M.T
显示剩余2条评论

14

你只需将tmpdir作为函数参数传递,因为它是一个py.test fixture。

def test_foo(tmpdir):
    # do things with tmpdir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接