pytest内置tmp_path fixture最简单可靠:每个测试前自动创建独立临时目录,测试后自动清理,返回pathlib.Path对象,无需手动管理。

pytest 中用 tmp_path fixture 最简单可靠
不用自己写 fixture,pytest 内置的 tmp_path 就是专为这个场景设计的:每个测试函数运行前自动创建独立临时目录,测试结束自动清理。它返回的是 pathlib.Path 对象,开箱即用。
- 直接在测试函数参数中声明
tmp_path,pytest 会自动注入 - 该目录路径唯一、隔离,不同测试间互不影响
- 无需手动
os.makedirs或shutil.rmtree,失败时也会尝试清理 - 比旧版
tmpdir(返回py.path.local)更现代、类型更清晰
def test_something(tmp_path):
data_file = tmp_path / "input.txt"
data_file.write_text("hello")
assert data_file.read_text() == "hello"
需要自定义临时目录结构?用 @pytest.fixture 包装 tmp_path
如果每个测试都需要预置子目录、配置文件或特定权限,可以在 fixture 中基于 tmp_path 构建,而不是从头 mktemp。这样既保留自动生命周期管理,又复用 pytest 的清理逻辑。
- fixture 作用域设为
"function"(默认),确保每测一个新目录 - 不要在 fixture 里调用
tempfile.mkdtemp()—— 那会脱离 pytest 管理,导致残留 - 可以安全地
mkdir、touch、chmod,所有操作都在tmp_path下
@pytest.fixture
def project_layout(tmp_path):
(tmp_path / "src").mkdir()
(tmp_path / "tests").mkdir()
(tmp_path / "pyproject.toml").write_text("[build-system]")
return tmp_path
def test_build_runs(project_layout):
assert (project_layout / "src").exists()
为什么不用 tempfile.TemporaryDirectory()?
手动用 tempfile.TemporaryDirectory() 容易出错:忘记 __enter__/__exit__、异常时未清理、多线程下路径冲突。pytest 的 tmp_path 在底层其实也用了类似机制,但封装了所有边界情况。
-
TemporaryDirectory返回字符串路径,不是Path,操作更啰嗦 - 若测试崩溃或被信号中断,它的
__exit__可能不执行,留下脏目录 - pytest 的清理逻辑会捕获测试异常、中断甚至 Ctrl-C,并尽力删除
- 和
tmp_path_factory配合还能跨测试共享(如 session 级缓存),TemporaryDirectory做不到
注意 tmp_path 和 tmp_path_factory 的分工
tmp_path 是函数级临时目录,够大多数场景;只有当你需要在 fixture 中动态生成多个目录、或想控制根路径位置(比如统一放在 SSD 分区),才用 tmp_path_factory。
-
tmp_path_factory.mktemp("name")创建子目录,仍受 pytest 清理管辖 -
tmp_path_factory.getbasetemp()能查到所有临时目录父路径,调试时有用 - 别把
tmp_path_factory当成替代品 —— 多数时候,直接参数化tmp_path更直白
真正容易被忽略的是:临时目录名带随机后缀,但路径本身不加密、不隐藏;如果测试里打印了 tmp_path,CI 日志里会暴露真实路径结构 —— 这在审计敏感环境时可能是个小隐患。










