如何在测试中使用临时目录和文件

tmp_path fixture

您可以使用 tmp_path fixture,它将为每个测试函数提供一个唯一的临时目录。

tmp_path 是一个 pathlib.Path 对象。这是一个示例测试用法

# content of test_tmp_path.py
CONTENT = "content"


def test_create_file(tmp_path):
    d = tmp_path / "sub"
    d.mkdir()
    p = d / "hello.txt"
    p.write_text(CONTENT, encoding="utf-8")
    assert p.read_text(encoding="utf-8") == CONTENT
    assert len(list(tmp_path.iterdir())) == 1
    assert 0

运行此操作将导致测试通过,除了最后一行 assert 0,我们用它来查看值

$ pytest test_tmp_path.py
=========================== test session starts ============================
platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y
rootdir: /home/sweet/project
collected 1 item

test_tmp_path.py F                                                   [100%]

================================= FAILURES =================================
_____________________________ test_create_file _____________________________

tmp_path = PosixPath('PYTEST_TMPDIR/test_create_file0')

    def test_create_file(tmp_path):
        d = tmp_path / "sub"
        d.mkdir()
        p = d / "hello.txt"
        p.write_text(CONTENT, encoding="utf-8")
        assert p.read_text(encoding="utf-8") == CONTENT
        assert len(list(tmp_path.iterdir())) == 1
>       assert 0
E       assert 0

test_tmp_path.py:11: AssertionError
========================= short test summary info ==========================
FAILED test_tmp_path.py::test_create_file - assert 0
============================ 1 failed in 0.12s =============================

默认情况下,pytest 保留最近 3 次 pytest 调用的临时目录。通过配置基本临时目录对于每次并发运行都是唯一的,可以支持同一测试函数的并发调用。有关详细信息,请参阅 临时目录位置和保留

tmp_path_factory fixture

tmp_path_factory 是一个 session 作用域的 fixture,可用于从任何其他 fixture 或测试创建任意临时目录。

例如,假设您的测试套件需要在磁盘上有一个大的图像,该图像是程序化生成的。与其为每个使用它的测试在其自己的 tmp_path 中计算相同的图像,不如每个会话生成一次以节省时间

# contents of conftest.py
import pytest


@pytest.fixture(scope="session")
def image_file(tmp_path_factory):
    img = compute_expensive_image()
    fn = tmp_path_factory.mktemp("data") / "img.png"
    img.save(fn)
    return fn


# contents of test_image.py
def test_histogram(image_file):
    img = load_image(image_file)
    # compute and test histogram

有关详细信息,请参阅 tmp_path_factory API

tmpdirtmpdir_factory fixtures

tmpdirtmpdir_factory fixtures 类似于 tmp_pathtmp_path_factory,但使用/返回旧式的 py.path.local 对象,而不是标准的 pathlib.Path 对象。

注意

现在,建议使用 tmp_pathtmp_path_factory

为了帮助现代化旧代码库,可以禁用 legacypath 插件运行 pytest

pytest -p no:legacypath

这将触发使用旧路径的测试中的错误。它也可以作为配置文件中 addopts 参数的一部分永久设置。

有关详细信息,请参阅 tmpdir tmpdir_factory API。

临时目录位置和保留

临时目录,由 tmp_path 和(现在已弃用的)tmpdir fixtures 返回,在基本临时目录下自动创建,其结构取决于 --basetemp 选项

  • 默认情况下(当未设置 --basetemp 选项时),临时目录将遵循此模板

    {temproot}/pytest-of-{user}/pytest-{num}/{testname}/
    

    其中

    自动递增的 {num} 占位符提供了一个基本的保留功能,并避免盲目删除先前测试运行的现有结果。默认情况下,保留最后 3 个临时目录,但可以使用 tmp_path_retention_counttmp_path_retention_policy 配置此行为。

  • 当使用 --basetemp 选项时(例如 pytest --basetemp=mydir),它将直接用作基本临时目录

    {basetemp}/{testname}/
    

    请注意,在这种情况下没有保留功能:仅保留最近一次运行的结果。

    警告

    在每次测试运行之前,将盲目清除提供给 --basetemp 的目录,因此请确保仅将目录用于此目的。

当使用 pytest-xdist 在本地计算机上分发测试时,会注意自动为子进程配置 basetemp 目录,以便所有临时数据都位于每个测试运行的单个临时目录之下。