pytest全局动态变量应写在conftest.py中,通过pytest_configure钩子注入config对象,并用session级fixture封装复用;不可写入pytest.ini或pyproject.toml等静态配置文件。

pytest配置全局变量该写在哪儿
全局动态变量不能塞进 pytest.ini 或 pyproject.toml 的静态配置节里——那些只接受字符串/布尔/列表字面量,不执行代码。真正能跑逻辑、生成动态值的地方只有两个:conftest.py(推荐)和自定义的 pytest_configure 钩子函数。
优先选 conftest.py,因为它天然支持模块级作用域,且会被自动导入所有测试文件;而钩子函数需要显式注册,容易漏掉或误配。
用 pytest_configure 注入动态值到 config 对象
这是最正统的“全局变量”注入方式:把值挂到 config 实例上,后续所有 fixture 和测试都能通过 request.config 或直接访问 pytestconfig fixture 拿到。
- 在项目根目录或测试目录下新建
conftest.py - 实现
pytest_configure(config)函数,注意函数名必须完全匹配,且带config参数 - 动态计算的值(比如当前时间戳、环境标识、随机 token)赋给
config._metadata或自定义属性(如config._my_dynamic_var = ...) - 避免覆盖内置属性(如
config.option、config.args),否则可能破坏 pytest 行为
示例:
立即学习“Python免费学习笔记(深入)”;
def pytest_configure(config):
import time
config._dynamic_timestamp = int(time.time() * 1000)
config._env_name = config.getoption("--env", default="dev")
在 fixture 中封装并复用动态值
直接读 config 属性不够安全:一是没类型提示,二是容易拼错属性名,三是无法做懒加载或缓存。更稳的方式是用 fixture 封装。
- 在
conftest.py中定义scope="session"的 fixture - fixture 函数体内调用
request.config获取之前注入的值 - 可在此处补全逻辑,比如根据
_env_name加载对应 YAML 配置、初始化数据库连接等 - 测试函数只需声明参数名(如
dynamic_config),pytest 自动注入
示例:
立即学习“Python免费学习笔记(深入)”;
@pytest.fixture(scope="session")
def dynamic_config(request):
cfg = request.config
return {
"timestamp": getattr(cfg, "_dynamic_timestamp", 0),
"env": getattr(cfg, "_env_name", "unknown"),
"api_base": f"https://api.{getattr(cfg, '_env_name', 'dev')}.example.com"
}
命令行参数如何影响动态变量值
动态变量常需响应 --env staging 这类传参。关键点在于:参数必须提前声明,否则 config.getoption() 会报 ValueError。
- 在
conftest.py中实现pytest_addoption(parser) - 用
parser.addoption("--env", action="store", default="dev")注册选项 - 确保
pytest_configure在pytest_addoption之后执行(pytest 保证这个顺序) - 不要在
addoption里做耗时操作,它在 pytest 初始化早期就运行,会影响启动速度
常见坑:getoption 第二个参数是默认值,不是 fallback 函数;如果想按条件返回不同值,得自己写逻辑包裹。
真正的难点不在“怎么设”,而在“什么时候读”——fixture 的 scope、config 属性的生命周期、命令行解析时机这三者稍有错位,就会出现值为空或旧值残留。尤其当多个 conftest.py 嵌套存在时,务必确认你修改的是 pytest 实际加载的那个文件。


















