Hook 方法之 pytest_addoption :
pytest_addoption 可以让用户注册一个自定义的命令行参数,方便用户将数据传递给pytest;
这个 Hook 方法一般和 内置 fixture pytestconfig 配合使用,pytest_addoption 注册命令行参数,pytestconfig 通过配置对象读取参数的值;
考虑场景:
- 我们的自动化用例需要支持在不同测试环境运行,有时候在dev环境运行,有时候在test环境运行;
- 有时候需要根据某个参数不同的参数值,执行不同的业务逻辑;
上面的场景我们都可以通过“在命令行中输入参数,然后用例中接收这个参数,通过判断这个参数的值来做不同的逻辑”来实现。那么我们的需求就变为pytest中如何自定义一个命令行参数呢?这时候我们就需要用到pytest的钩子函数:pytest_addoption。
parser.addoption() 参数说明:
name:自定义命令行参数的名字,可以是:"foo", "-foo" 或 "--foo"; action:在命令行中遇到此参数时要采取的基本操作类型; nargs:应该使用的命令行参数的数量; const:某些操作和nargs选择所需的常量值; default:如果参数不在命令行中,则生成的默认值。 type:命令行参数应该转换为的类型; choices:参数允许值的容器; required:命令行选项是否可以省略(仅可选); help:对参数作用的简要说明; metavar:用法消息中参数的名称; dest:要添加到 parse_args() 返回的对象中的属性的名称;
对parser.addoption() 参数解释:
1. name:这个不用多说,自定义的参数的名字;
2. action 、default 和 const、help :
action="store":默认,只存储参数的值,可以存储任何类型的值,此时 default 也可以是任何类型的值,而且命令行参数多次使用也只能生效一个,最后一个值覆盖之前的值;
# 注册自定义参数 cmdopt 到配置对象 def pytest_addoption(parser): parser.addoption("--cmdopt", action="store", default="这个是默认值...", help="将命令行参数 ’--cmdopt' 添加到 pytest 配置中") # 从配置对象中读取自定义参数的值 @pytest.fixture(scope="session") def cmdopt(request): return request.config.getoption("--cmdopt") # 将自定义参数的值打印出来 @pytest.fixture(autouse=True) def fix_1(cmdopt): print('\n --cmdopt的值:',cmdopt) if __name__ == '__main__': # 使用参数 pytest.main(['-s', '--cmdopt=98k'])
运行结果:
action="append":存储一个列表,用 append 模式 将可以同时多次使用自定义参数,并且 default 默认值必须是一个列表,pytest 会把 default 默认参数的值和多个自定义参数的值放在一个列表中:
# 注册自定义参数 cmdopt 到配置对象 def pytest_addoption(parser): parser.addoption("--cmdopt", action="append", default=['这是默认参数'], help="将命令行参数 ’--cmdopt' 添加到 pytest 配置中") if __name__ == '__main__': # 使用参数 pytest.main(['-s', '--cmdopt=98k', '--cmdopt=毛瑟小手枪'])
运行结果:
action="store_const":使用 const 为命令行参数指定一个常量值,必须和 const 参数同时使用,使用这个模式后命令行参数不能赋值:
def pytest_addoption(parser): parser.addoption("--cmdopt", action="store_const", default='这是默认参数', const='这个是为命令行参数指定的常量值...', help="将命令行参数 ’--cmdopt' 添加到 pytest 配置中") if __name__ == '__main__': pytest.main(['-s','--cmdopt'])
运行结果:
action="append_const":存储一个列表,使用 const 为命令行参数指定一个常量值,并将 default 默认值和 const 常量值添加到列表中,这个模式可以同时多次使用自定义参数,但是还是不能赋值,只能使用常量;
def pytest_addoption(parser): parser.addoption("--cmdopt", action="append_const", default=['这是默认参数'], const='这个是为命令行参数指定的常量值...', help="将命令行参数 ’--cmdopt' 添加到 pytest 配置中") if __name__ == '__main__': pytest.main(['-s','--cmdopt', '--cmdopt'])
运行结果:
3. type:type 的类型可以是 python 的基础类型,比如:int,str,float,list 等类型,如果不指定类型的话,pytest会把接受到的参数值都默认为 str 类型,所以我们有时需要指定参数的类型:
注意:在使用 type 指定类型时,也需要把 default 的类型修改为同样的类型!
def pytest_addoption(parser): parser.addoption("--cmdopt", action="store", default=100, type=int, help="将命令行参数 ’--cmdopt' 添加到 pytest 配置中") if __name__ == '__main__': pytest.main(['-s', f'--cmdopt=888'])
运行结果:
4. choices:choices 可以指定几个值,自定义参数必须在这几个值中选择一个,否则会报错:
def pytest_addoption(parser): parser.addoption("--cmdopt", action="store", default='100', choices= ['python', 'java', 'c++'], help="将命令行参数 ’--cmdopt' 添加到 pytest 配置中") if __name__ == '__main__': pytest.main(['-s', f'--cmdopt=888'])
运行结果:
实战举例:
通过conftest.py配置
新建一个conftest.py文件,然后在conftest.py文件中通过pytest_addoption方法来添加命令行参数,通过定义的fixture来获得参数的值。
# file_name: conftest.py import pytest def pytest_addoption(parser): parser.addoption( "--cmdopt", action="store", default="type1", help="my option: type1 or type2" ) parser.addoption( "--env", action="store", default="dev", help="env:表示测试环境,默认dev环境" ) # 从配置对象中读取自定义参数的值(一) @pytest.fixture() def cmdopt(pytestconfig): return pytestconfig.getoption("cmdopt") # 从配置对象中读取自定义参数的值(二) @pytest.fixture() def env(request): return request.config.getoption("--env")
上面conftest.py文件中新增了两个命令行参数:--cmdopt和--env;然后定义了两个fixture,在测试用例中想要获得参数--cmdopt的值,就可以调用cmdopt函数;调用env函数可以获取参数--env的值。
编写测试用例:
# file_name: test_option.py import pytest def test_option(env): if env == 'dev': print("当前测试环境为:{},域名切换为开发环境".format(env)) elif env == 'test': print("当前测试环境为:{},域名切换为测试环境".format(env)) else: print("环境错误,当前环境{}不存在".format(env)) if __name__ == '__main__': pytest.main(['-s', 'test_option.py'])
上面例子是获取env的值,针对env值的不同做不同的操作。
不带参数运行:
命令行中输入指令: pytest test_option.py -s ,运行结果:
因为我们在conftest.py文件中定义的参数env的默认值为dev,所以当运行时命令行不传env参数,则使用默认值dev。
带参数运行:
命令行中输入指令: pytest test_option.py -s --env=test ,运行结果:
从结果中可以看到,命令行中输入参数env=test,在测试用例中获取到通过fixture获取到env的值为test。