pytest-datadir是提供安全隔离测试数据路径的fixture插件,不解析内容,只返回指向临时副本的pathlib.path对象;datadir按模块名匹配同名子目录,shared_datadir固定查找项目根下data目录。

pytest-datadir 不是“读取数据的工具”,而是帮你安全、隔离、可复用地访问测试数据文件路径的 fixture 插件。它不负责解析内容,只确保你拿到的是一个干净、临时、指向正确位置的 pathlib.Path 对象。
datadir 和 shared_datadir 的实际行为差异
-
datadir会查找与当前测试模块同名的子目录(比如test_foo.py→ 自动找test_foo目录),并把该目录下的所有文件复制到临时路径中; -
shared_datadir固定查找项目根目录下名为data的全局目录(不依赖模块名),同样做复制; - 两者返回的都是
pathlib.Path实例,不是字符串,不能直接传给open()而不加.resolve()或.as_posix()(虽然通常不需要); - 所有文件操作都发生在临时副本上,原始文件不会被修改,即使你在测试里
.write_text()也没关系。
常见错误现象:
- 报错
FileNotFoundError: [Errno 2] No such file or directory: 'spam.txt'—— 很可能是因为没建对应目录,或目录名拼写不一致(比如test_spam.py但建了spam_data目录); - 读到空内容或旧内容 —— 可能误用了原始路径而非
datadir返回的临时路径; - Windows 上 PermissionError —— 是因为你没关掉文件句柄就尝试重复读写,而
pytest-datadir默认不帮你管理打开状态。
目录结构必须严格匹配才能被识别
你的项目结构得是这样(以 tests/ 为根):
tests/
├── test_example.py
├── test_example/ ← 必须和 test_example.py 同名(不含 .py)
│ └── input.json
└── data/ ← 全局共享目录,名字必须是 data
└── config.yaml
否则 datadir 就找不到东西。注意:
-
test_example/是目录,不是文件; - 名字区分大小写(Linux/macOS 下尤其敏感);
- pytest 默认只在
tests/或当前运行目录下找,不会向上递归到项目根; - 如果你把测试放在
src/tests/,那data/也得放在src/tests/data/,而不是项目根。
怎么读、写、校验文件才不出错
直接用 Path 对象的方法最稳妥:
✅ 推荐写法:
def test_load_config(shared_datadir):
cfg = (shared_datadir / "config.yaml").read_text(encoding="utf-8")
assert "version" in cfg
<p>def test_modify_input(datadir):
f = datadir / "input.json"
content = f.read_text()</p><h1>修改后写回(安全,只影响副本)</h1><pre class="brush:python;toolbar:false;">f.write_text(content.replace("old", "new"))
assert "new" in f.read_text()
⚠️ 容易踩的坑:
- 用
open(str(datadir / "x.txt"))—— 不必要,且丢失Path的链式能力; - 假设文件编码是系统默认(比如 Windows 的 cp1252)—— 显式传
encoding="utf-8"更可靠; - 对二进制文件(如图片、.xlsx)用
read_text()—— 改用read_bytes(); - 在测试中多次
.open(..., "w")覆盖同一文件却没 close ——Path.write_text()是原子操作,无需手动 close。
真正的复杂点不在“怎么读”,而在于什么时候该用 datadir,什么时候该用 tmp_path 或 tmpdir。pytest-datadir 只适合“已有静态样本数据”的场景;如果你需要生成中间文件、模拟上传流、或做破坏性写入测试,tmp_path(pytest 内置 fixture)才是更轻量、更可控的选择。别为了统一而硬套 datadir。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











