如何使用pytest monkeypatch模拟多个argv参数?
问题解决方法
你的代码有两个核心问题导致测试失败:
- argparse参数类型错误:你在
foo()里定义的是位置参数(不带--前缀),但测试里却用了--animal这种可选参数的写法,argparse会把--animal当成位置参数的值,自然找不到真正需要的animal和name参数。 - sys.argv被重复覆盖:你连续两次调用
m.setattr(sys, 'argv', ...),第二次的赋值直接覆盖了第一次,最终sys.argv里只有--name相关内容,完全缺失animal参数,引发参数缺失报错。
修改后的位置参数版本代码
### foo.py ### import argparse import pytest import sys @pytest.mark.parametrize('animal_input, name_input', [('cat', 'tom')]) def test_get_bake_progress(monkeypatch, animal_input, name_input): with monkeypatch.context() as m: # sys.argv[0]为脚本名(可随便填,argparse仅需占位),后续跟位置参数值 m.setattr(sys, 'argv', ['foo.py', animal_input, name_input]) assert foo() == animal_input def foo(): parser = argparse.ArgumentParser() parser.add_argument('animal') parser.add_argument('name') args = parser.parse_args() animal = args.animal name = args.name return animal
若想改为可选参数(带--前缀)的版本
如果你原本计划把animal和name做成带--的可选参数,可按以下方式修改:
### 可选参数版本 foo.py ### import argparse import pytest import sys @pytest.mark.parametrize('animal_input, name_input', [('cat', 'tom')]) def test_get_bake_progress(monkeypatch, animal_input, name_input): with monkeypatch.context() as m: m.setattr(sys, 'argv', ['foo.py', '--animal', animal_input, '--name', name_input]) assert foo() == animal_input def foo(): parser = argparse.ArgumentParser() parser.add_argument('--animal', dest='animal') parser.add_argument('--name', dest='name') args = parser.parse_args() animal = args.animal name = args.name return animal
补充说明:
- 用
@pytest.mark.parametrize把测试参数组合成元组,更清晰地传递一组测试数据。 sys.argv的第一个元素必须保留脚本名占位,argparse解析时会自动忽略该值。
内容的提问来源于stack exchange,提问作者jjk
相关产品推荐
相关产品推荐

