Python argparse parse_args()报错:pytest集成测试配置读取失败
问题描述
编写基于pytest的集成测试代码时,创建了供子类继承的父类BaseTestClass,希望从yaml资源文件读取动态配置实现环境切换。但执行代码时,args = parser.parse_args()行触发错误,提示无法识别pytest传入的测试路径参数,最终抛出SystemExit:2。
test_base.py
import yaml import pytest import argparse class BaseTestClass: @classmethod def configure(cls): print('Configure') # 从命令行参数读取环境信息 parser = argparse.ArgumentParser() parser.add_argument('--env', choices=['local', 'dev', 'qa', 'prod'], help='执行环境', default='local') args = parser.parse_args() # 报错位置 env = args.env with open(f"resources/config-{env}.yaml", 'r') as file: properties = yaml.safe_load(file) cls.config = properties @pytest.fixture(autouse=True) def configure_parent(self): self.configure()
错误日志
ERROR [100%]Configure usage: _jb_pytest_runner.py [-h] [--env {local,dev,qa,prod}] _jb_pytest_runner.py: error: unrecognized arguments: /Users/agstcadini/Projects/quinta/quinta-app/python/quinta-backend/tests/integration test setup failed self = <test_api.TestApi object at 0x10dc523d0> @pytest.fixture(autouse=True) def configure_parent(self): > self.configure() test_base.py:24: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ test_base.py:16: in configure args = parser.parse_args() /usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/argparse.py:1827: in parse_args self.error(msg % ' '.join(argv)) /usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/argparse.py:2581: in error self.exit(2, _('%(prog)s: error: %(message)s\n') % args) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = ArgumentParser(prog='_jb_pytest_runner.py', usage=None, description=None, formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True) status = 2 message = '_jb_pytest_runner.py: error: unrecognized arguments: /Users/agstcadini/Projects/quinta/quinta-app/python/quinta-backend/tests/integration\n' def exit(self, status=0, message=None): if message: self._print_message(message, _sys.stderr) > _sys.exit(status) E SystemExit: 2 /usr/local/Cellar/python@3.9/3.9.10/Frameworks/Python.framework/Versions/3.9/lib/python3.9/argparse.py:2568: SystemExit
文件系统结构
% tree -v -L 2 . ├── __pycache__ │ ├── test_api.cpython-39-pytest-7.3.1.pyc │ └── test_base.cpython-39-pytest-7.3.1.pyc ├── report.json ├── resources │ ├── config-dev.yaml │ └── config-local.yaml ├── test_api.py └── test_base.py
config-local.yaml
endpoint: host: localhost port: 8081
解决方案
问题根源
直接使用argparse.ArgumentParser()会解析所有命令行参数,包括pytest自身的参数(比如测试路径、内置参数),这些参数不在自定义的--env范围内,因此触发参数不识别错误,导致程序退出。
解决办法
改用pytest原生的自定义命令行参数机制,避免和pytest的参数解析冲突:
- 修改
test_base.py,利用pytest的pytest_addoption钩子定义参数,通过requestfixture获取参数值:
import yaml import pytest def pytest_addoption(parser): parser.addoption( "--env", choices=['local', 'dev', 'qa', 'prod'], help='执行环境', default='local' ) class BaseTestClass: @classmethod def configure(cls, env): print('Configure') with open(f"resources/config-{env}.yaml", 'r') as file: properties = yaml.safe_load(file) cls.config = properties @pytest.fixture(autouse=True) def configure_parent(self, request): # 获取pytest命令行传入的--env参数 env = request.config.getoption("--env") self.configure(env)
- 执行测试时,直接通过pytest传递参数:
pytest tests/integration --env dev
额外优化
如果希望配置在会话级别加载一次,无需每个测试类重复读取文件,可以用会话级fixture实现:
import yaml import pytest def pytest_addoption(parser): parser.addoption( "--env", choices=['local', 'dev', 'qa', 'prod'], help='执行环境', default='local' ) @pytest.fixture(scope="session", autouse=True) def load_env_config(request): env = request.config.getoption("--env") with open(f"resources/config-{env}.yaml", 'r') as file: config = yaml.safe_load(file) # 将配置存入pytest的config对象,供所有测试访问 request.config._env_config = config class BaseTestClass: @pytest.fixture(autouse=True) def inject_config(self, request): self.config = request.config._env_config
这样所有继承BaseTestClass的测试类都会自动获取到环境配置,配置文件仅在测试会话启动时读取一次,提升效率。
内容的提问来源于stack exchange,提问作者Augusto
相关产品推荐
相关产品推荐

