前言
pytest这个框架提供了非常多的钩子。通过这些钩子我们可以对pytest 用例收集、用例执行、报告输出等各个阶段进行干预,根据需求去开发对应的插件,以满足自己的使用场景。
01 什么是钩子函数?
钩子函数在pytest称之为Hook函数,它pytest框架的开发者,为了让用户更好的去扩展开发预留的一些函数。而预留的这些函数,在整个测试执行的生命周期中特定的阶段会自动去调用执行。如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aJh4ShrP-1689820417032)(/api/attachments/426316)]
pytest中的钩子函数按功能一共分为6类:引导钩子,初始化钩子、用例收集钩子、用例执行钩子、报告钩子、调试钩子。
详细文档可以查看pytest官方文档https://docs.pytest.org/en/latest/reference/reference.html?highlight=hook#hooks
02 初始化钩子
初始化钩子用来调用插件和conftest.py文件的初始化。
2.1 pytest_addoption
参数
- parser :参数解析器
- pluginmanager :插件管理器
触发时机:
- conftest文件加载完之后执行, 在测试运行开始时调用一次。
作用:
- 添加运行命令的命令行参数,pytest.ini的配置参数。
2.1.1 parser.addoption
pytest_addoption 钩子函数可以让用户注册一个自定义的命令行参数,以便于用户在测试开始前将数据从外部(如:控制台)传递给程序。
parser.addoption 方法接收以下几个参数:
- name:自定义命令行参数的名字,可以是短选项(例如 -n)或长选项(例如 --name)。
- action:在命令行中遇到此参数时要采取的存储该参数对应的参数值的基本操作类型;
- default:如果参数不在命令行中,则生成的默认值。
- dest:要添加到 parse_args() 返回的对象中的属性的名称;
- type:注册的自定义到pytest配置对象中的命令行参数对应的参数值应该转换为的类型;可以是 int、float、str 等类型,默认为 str。
- choices:参数允许值的容器;传递了 choices 参数后,只有在选项的值在这个列表中时才会被接受。
- help:对参数作用的简要说明;将在命令行中显示帮助信息时使用。
- nargs:应该使用的命令行参数的数量;
- const:某些操作和nargs选择所需的常量值;
- required:命令行选项是否可以省略(仅可选);
- metavar:用法消息中参数的名称;
其中action参数有几个预定义的选项可供选择,包括:
- store(默认): 将选项值存储到相应的目标变量中。
- store_const: 存储一个常量值到相应的目标变量中。
- store_true: 存储 True 到相应的目标变量中。
- store_false: 存储 False 到相应的目标变量中。
- append: 将多个值追加到相应的目标变量中,用于处理多次出现的选项。
- count: 计算选项的出现次数,并将次数存储到相应的目标变量中。
2.1.1.1 通过自定义命令行参数-env设置当前运行的环境
# conftest.py
def pytest_addoption(parser, pluginmanager):
parser.addoption(
"--env",
dest="env_value",
action="store",
default="test",
choices=["test", "live"],
help="通过自定义命令行参数-env设置当前运行的环境"
)
# ----------------------------------------------------------------------------#
# test_demo.py
import pytest
cases = [
{"id": 1, "title": "demo 001", "username": "flora"},
# {"id": 2, "title": "demo 002", "username": "lucy"},
]
class TestDemo:
@pytest.mark.parametrize("case", cases)
def test_demo(self, case, request):
env = request.config.getoption("env_value")
# 由于 parser.addoption存在参数dest因此需要使用dest的值来获取命令行参数的值,如果没有dest,则可以采用env = request.config.getoption("env")获取命令行参数的值
print("获取到的env的值:", env)
assert case["username"] == "flora"
通过命令pytest -s --env=live
运行测试,结果如下:
2.1.2 parser.addini
parser.addini 方法用于向解析器添加配置文件选项。parser.addini 方法可以接收以下参数:
- name(必需):配置选项的名称,它应该是一个字符串。
- help(可选):配置选项的帮助文本,用于描述配置选项的作用和使用方法。
- type(可选):配置选项的类型,默认为字符串类型。
- default(可选):配置选项的默认值,如果用户没有在配置文件中指定该选项,则将使用默认值。
- **kwargs(可选):其他关键字参数,用于进一步自定义配置选项。
2.1.2.1 往pytest配置文件中添加参数
# conftest.py
import pytest
def pytest_addoption(parser, pluginmanager):
parser.addoption(
"--env",
# dest="env_value",
action="store",
default="test",
choices=["test", "live"],
help="通过自定义命令行参数-env设置当前运行的环境"
)
parser.addini(
'live_host',
type="string",
default="https://www.gitlink.org.cn/",
help='正式环境域名'
)
parser.addini(
'test_host',
type="string",
default="https://www.test.org.cn/",
help='测试环境域名'
)
# 获取 pytest.ini 配置参数
@pytest.fixture(scope="session")
def get_host(pytestconfig, request):
env = request.config.getoption("env")
if env == "test":
host = pytestconfig.getini('test_host')
elif env == "live":
host = pytestconfig.getini('live_host')
else:
host = ""
print(f"\n当前环境域名是:{host}")
通过命令pytest -s --env=live
运行测试,结果如下:
2.2 pytest_configure
参数
- config:pytest 配置对象,提供了许多方法和属性来获取和修改 pytest 的配置选项。例如,可以使用 config.getoption(name) 来获取命令行选项的值,使用 config.getini(name) 来获取配置文件选项的值。
触发时机:
- 在解析命令行选项后,每个插件和初始 conftest 文件都会调用此钩子,
- 在导入其他 conftest 文件时调用该钩子。
默认作用:
- 允许插件和 conftest 文件执行初始配置。
2.2.1 往配置文件中添加自定义标记并读取所有标记
# conftest.py
def pytest_addoption(parser, pluginmanager):
parser.addoption(
"--env",
# dest="env_value",
action="store",
default="test",
choices=["test", "live"],
help="通过自定义命令行参数-env设置当前运行的环境"
)
def pytest_configure(config):
# 获取命令行选项的值
my_option = config.getoption('env')
print(f"获取到的命令行选项值为:{my_option}")
# 添加自定义配置
config.addinivalue_line("markers", "demo: democase")
print("已添加自定义标记 'custom_marker'")
# 获取配置文件选项的值
my_ini_option = config.getini('markers')
print(f"获取到的配置文件选项值为:{my_ini_option}")
# test_demo.py
import pytest
cases = [
{"id": 1, "title": "demo 001", "username": "flora", "age": 17},
# {"id": 2, "title": "demo 002", "username": "lucy", "age": 18},
]
class TestDemo:
@pytest.mark.demo
@pytest.mark.parametrize("case", cases)
def test_demo_01(self, case):
assert case["username"] == "flora"
@pytest.mark.parametrize("case", cases)
def test_demo_02(self, case):
assert case["age"] == 18
通过命令pytest -s --env=live -m=demo
运行测试,结果如下:
2.3 pytest_unconfigure
参数
- config:pytest配置对象。
触发时机:
- 在退出测试过程之前调用。
2.4 pytest_sessionstart
参数
- session:pytest 会话对象,它提供了许多方法和属性来获取和修改测试会话的各种信息。例如,可以使用 session.config 来访问 pytest 的配置对象,使用 session.items 获取当前会话中的测试项,以及使用其他方法来处理测试会话相关的信息。
触发时机:
- 在创建 Session 对象之后、执行收集测试用例之前调用。
以下是一些常用的 session 属性和方法:
- session.config:获取当前 pytest 配置对象,可以使用它来获取和修改 pytest 的配置选项。
- session.shouldstop:用于判断是否应该停止测试会话。在测试过程中,可以设置 session.shouldstop = True 来提前终止测试会话。
- session.testsfailed:获取测试失败的数量。
2.5 pytest_sessionfinish
参数:
- session:pytest 会话对象。
- exitstatus:pytest 将返回系统的状态。
触发时机:
- 在整个测试运行完成后调用,就在将退出状态返回给系统之前。
以下是一些常用的 session 属性和方法:
- session.config:获取当前 pytest 配置对象,可以使用它来获取和修改 pytest 的配置选项。
- session.shouldstop:用于判断是否应该停止测试会话。在测试过程中,可以设置 session.shouldstop = True 来提前终止测试会话。
- session.testsfailed:获取测试失败的数量。
2.6 pytest_plugin_registered
参数
- plugin :插件模块或实例。
- manager :pytest 插件管理器。
作用:
- 注册一个新的插件。
2.7 pytest_addhooks
参数
- pluginmanager :插件管理器。
触发时机:
- 注册插件时调用,添加钩子函数到执行列表。
默认作用:
- 调用 pluginmanager.add_hookspecs(module_or_class, prefix) 注册插件。