pytest-env 不加载环境变量,只将配置写入os.environ;需在pyproject.toml中正确配置env列表,值含空格须加引号,不支持变量插值,且仅启动时生效。

pytest-env 不能直接“加载”环境变量,它只负责把配置写入 os.environ —— 你得先有配置,它才帮你塞进去。
为什么 pytest-env 看起来没生效?
常见现象是:在测试里打印 os.environ.get("API_URL") 仍为 None,但 pytest.ini 明明写了。
- 根本原因:pytest-env 不读取系统环境变量、不解析
.env文件、不自动加载任何外部源 —— 它只认自己配置文件里的[tool:pytest] env或[pytest] env区块 - 典型误用:以为装了插件就自动接管所有环境变量,结果变量根本没进
os.environ - 兼容性注意:新版 pytest(≥7.0)推荐用
pyproject.toml;旧版用pytest.ini,格式稍有差异
如何正确配置 pyproject.toml(推荐)
这是当前最稳定的方式,避免 INI 解析歧义。
[tool.pytest.ini_options] env = [ "API_URL=https://api.test.example.com", "DB_NAME=testdb", "LOG_LEVEL=DEBUG", ]
- 每行一个
KEY=VALUE,等号前后不能有空格 - 值中若含空格或特殊字符,**必须加引号**:
"PATH=/usr/local/bin:/opt/bin" - 不支持变量插值(比如
HOME不会自动展开),全靠硬编码或 CI 注入 - 该配置只在 pytest 启动时生效,运行中修改
os.environ不会影响后续测试的初始状态
如何验证变量是否真被加载?
别依赖日志或外部服务响应,直接查 os.environ。
立即学习“Python免费学习笔记(深入)”;
在任意测试函数里加:
def test_env_loaded():
assert os.environ.get("API_URL") == "https://api.test.example.com"
assert "DB_NAME" in os.environ
- 更稳妥的做法:在
conftest.py的pytest_configure钩子中检查并报错 - 注意:
os.environ是全局可变的,如果某个测试擅自del os.environ["API_URL"],后续测试可能失效 - 调试时可用
print(dict(os.environ))快速 dump 全量,但别提交到代码库
和 python-dotenv 混用时的坑
很多人想“本地用 .env,CI 用 pytest-env”,结果变量被覆盖或冲突。
- 顺序很重要:如果
conftest.py里提前调用了load_dotenv(),它会先写入os.environ;之后 pytest-env 再写同名 KEY,会覆盖前者 - 反向也成立:pytest-env 先写,你再
load_dotenv(override=True),也会覆盖掉 pytest-env 的值 - 建议方案:开发时禁用 pytest-env,靠
python-dotenv;CI 时删掉.env文件,只靠 pytest-env 配置,避免双写逻辑 - 绝对不要在
pytest.ini或pyproject.toml里写敏感值(如密钥),应由 CI 系统通过--env参数注入(需配合pytest-env的命令行支持)
真正麻烦的不是配置语法,而是变量生命周期管理——pytest-env 只管启动那一刻的快照,之后怎么用、会不会被改、要不要隔离,都得你自己兜底。


















