必须在conftest.py中定义pytest_addoption钩子注册参数,如--env和--timeout,并指定type与default;测试中须通过request.config.getoption("env")安全读取,不可用sys.argv或顶层调用。

pytest 支持自定义命令行选项传递参数,但必须通过 pytest_addoption 钩子注册,且在测试函数中用 request 或 config 获取 —— 直接用 sys.argv 或 argparse 会失效。
如何注册自定义命令行选项(pytest_addoption)
必须在 conftest.py 中定义 pytest_addoption 钩子函数,不能放在测试文件或普通模块里。pytest 启动时只扫描 conftest.py 来加载配置。
- 选项名推荐用
--xxx形式(如--env),避免单字符(-e)以防和内置选项冲突 - 类型要显式指定:
type=str、type=int,否则默认是字符串,数值类参数容易出错 - 加
action="store_true"表示布尔开关;加default=...设置默认值,否则值为None
def pytest_addoption(parser):
parser.addoption(
"--env",
action="store",
type=str,
default="staging",
help="Target environment: staging, prod, or dev"
)
parser.addoption(
"--timeout",
action="store",
type=int,
default=30,
help="API timeout in seconds"
)
如何在测试函数中获取命令行参数(request.config.getoption)
不能用 sys.argv 解析,pytest 的命令行参数只对 config 对象可见。最稳妥的方式是在测试函数中通过 request fixture 拿到 config,再调用 getoption。
-
request是 pytest 内置 fixture,无需导入,直接作为参数传入测试函数即可 - 选项名要去掉
--前缀,比如--env对应request.config.getoption("env") - 如果选项未传且没设
default,getoption会返回None,需自行判空处理
def test_api_endpoint(request):
env = request.config.getoption("env")
timeout = request.config.getoption("timeout")
assert env in ("dev", "staging", "prod")
assert timeout > 0
为什么不能在 setup_module 或全局作用域读取参数?
因为 pytest_addoption 在 pytest 初始化阶段执行,而模块级的 setup_module 或顶层代码运行时机早于 config 完全构建完成,此时 pytestconfig fixture 还不可用,强行访问会报 AttributeError: 'Config' object has no attribute 'getoption' 或返回空值。
立即学习“Python免费学习笔记(深入)”;
- 唯一安全的全局访问方式是通过
pytest_configure钩子,在 config 就绪后挂载变量(不推荐,易引发耦合) - 更推荐把参数提取逻辑封装成 fixture,用
@pytest.fixture(scope="session")+request.config.getoption,让所有测试按需依赖 - 不要试图在
__init__.py或setup.py里解析 pytest 参数 —— 它们根本不在 pytest 生命周期内
常见错误:参数被忽略或始终取默认值
最常踩的坑是命令行写了选项但测试里读不到,基本就三种原因:
- 选项注册在错误位置:比如写在
test_*.py里,pytest 根本不会执行它 - 调用时拼写错误:
pytest --ennv=prod(多打个 n)或pytest --env prod(漏等号,某些版本不兼容空格分隔) - IDE 运行配置未同步:PyCharm 的 pytest 配置里没勾选「Add content roots to PYTHONPATH」,导致
conftest.py未被发现
验证是否生效,加一句 print(request.config.getoption("env")) 到测试里,再跑 pytest --env=prod -s 看输出 —— 比查文档快得多。


















