pytest.ini可通过自定义--environment参数配合conftest.py中pytest_addoption注册及session级config fixture,实现dev/staging/prod多环境变量加载与测试精准分发。

用 pytest.ini 配置多个 environment 变量
pytest 本身不内置“多环境”概念,但可以通过 addopts + 自定义命令行参数 + fixture 组合实现。核心是让测试能感知当前运行在哪套环境(如 dev、staging、prod),而不是硬编码 URL 或配置路径。
在项目根目录放 pytest.ini,声明自定义参数并设默认值:
[tool:pytest]
addopts = --environment=dev
markers =
env: mark a test to run only in specific environment
这样执行 pytest 默认走 dev,加 --environment=staging 就切换。
通过 pytest_addoption 注册 --environment 参数
在 conftest.py 里注册参数,才能被 pytest 解析并传给 fixture:
def pytest_addoption(parser):
parser.addoption(
"--environment",
action="store",
default="dev",
help="Environment to run tests against (dev/staging/prod)"
)
注意:必须放在 conftest.py(且通常在项目根或 tests/ 目录下),不能写在普通 test_*.py 文件里,否则参数不生效。
常见错误:
- 忘记在
conftest.py中定义该函数 → 运行pytest --environment=xxx报错unrecognized arguments - 参数名写成
--env但没同步改addopts→ 默认值失效,实际取None导致后续报错
用 fixture 读取 environment 并加载对应配置
定义一个 config fixture,根据 --environment 值加载不同 YAML/JSON 配置文件:
@pytest.fixture(scope="session")
def config(request):
env = request.config.getoption("--environment")
config_path = f"configs/{env}.yaml"
with open(config_path) as f:
return yaml.safe_load(f)
这样每个测试函数只要声明 def test_login(config):,就能拿到当前环境的 base_url、api_token 等。
关键点:
- 用
scope="session"避免重复读文件 - 路径拼接要校验存在,建议加
assert os.path.exists(config_path),否则报错信息模糊(只说FileNotFoundError,不提示是哪个 env) - 不要在 fixture 里做耗时操作(比如请求远程配置中心),会拖慢整个测试 session 启动
按 environment 标记跳过不匹配的测试
有些测试只应在特定环境运行(比如 prod 环境禁止删库操作),可用 pytest 的 mark 控制:
@pytest.mark.env("staging", "prod")
def test_send_notification(config):
...
然后在 conftest.py 加逻辑跳过不匹配的:
def pytest_runtest_makereport(item, call):
if "env" in item.keywords:
envs = item.keywords["env"].args
current_env = item.config.getoption("--environment")
if current_env not in envs:
pytest.skip(f"Skipping {item.name}: requires env in {envs}")
这个逻辑容易漏掉的是:如果标记了 @pytest.mark.env("dev") 但命令行传了 --environment=staging,测试直接跳过——不会报错也不会提醒,得靠 CI 日志人工核对是否误跳。
最常被忽略的一点:环境配置文件本身(如 configs/staging.yaml)不该进 Git,尤其含密钥或账号。要用 .gitignore 拦住,再靠 CI 注入或本地 symlink 管理。否则一套配置误推到 prod,后果不是重跑测试能解决的。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











