@property 作用是什么?:
@property 是 Python 内置的一个装饰器,它的核心作用非常优雅:让你能把一个方法"伪装"成一个普通的属性(变量)来调用。用大白话翻译就是:去掉方法名后面的小括号 ()。
正常情况下,你读取 YAML 数据需要这样写(带括号):
python
req = RequestBase()
data = req.get_yaml_data() # 注意这里有括号
但如果你在 get_yaml_data 方法上加了 @property,调用时括号就可以省略了:
python
req = RequestBase()
data = req.get_yaml_data # 注意这里没有括号,就像访问普通属性一样
什么是钩子函数?:
"钩子函数"(Hook Function) 是理解 pytest 框架 核心机制的关键词。用一句话说人话就是:
钩子函数 = 框架预先埋好的"事件监听器"。当程序运行到特定时刻(比如刚开始、跑完一个用例、全部结束),框架会自动"触发"这些函数,让你有机会插进去执行自己的自定义代码。
接口的名字通常以 pytest_ 开头
钩子函数 = 框架给的"插口"。你只要按照 conftest.py 里规定的函数名写,不用管它什么时候运行,pytest 到了那个时间节点自动回头执行它。
@pytest.fixture(scope="session", autouse=True)这句是什么意思?:
这句话是 pytest 框架中最核心、最高频使用的配置之一。
你可以把这句装饰器理解为:"定义一个全自动、全局只执行一次的启动前保洁员"。
定义一个自动运行的初始化函数,它会在整个测试套件启动时(session)且只在一开始时(仅一次),默默地(autouse=True)把旧数据清掉、把残留报告删掉,不用每个用例单独去调用它。
1.这是 Python 的装饰器语法,它告诉 pytest:"下面这个函数不是普通的工具函数,而是一个'固件(Fixture)'。"
固件(Fixture) 在测试里的角色是:提供测试所需的前置资源或环境准备(比如:创建数据库连接、生成测试数据、清理垃圾文件)。
2.scope="session" ------ 作用范围(管多久?)
scope 参数决定了这个固件什么时候执行一次,以及执行结果能管多久。
"session" 是作用域最大的一种,意味着:在整个 pytest 测试会话中,这个固件只会在最开始执行 1 次,所有的测试用例(无论几百个)都共享这一次执行的效果。
对比其他 scope 帮你建立记忆锚点:
scope="function"(默认):每个用例执行前都跑一次(最频繁)。
scope="class":每个测试类执行前跑一次。
scope="module":每个 .py 文件执行前跑一次。
scope="session":整个测试任务(比如你运行 pytest 命令的整个过程)只跑一次。
3.autouse=True ------ 触发方式(怎么启动?)
autouse 直译是"自动使用"。
正常情况下,你想让一个固件生效,必须在测试用例的参数里写上它的名字(比如 def test_case(clear_extract):)。
加了 autouse=True 之后,你不需要在任何测试用例里去声明它。pytest 会在合适的时机(根据 scope 决定)自动、无条件地调用这个函数。
你代码里写的是 autouse=True,配合 scope="session",就变成了:"只要我一运行 pytest,不用打招呼,系统自动先把环境清理干净,且只清理这一次。"
测试用例的命名:
pytest 遍历 ./testcase 下的所有文件,把里面的 def test_xxx 函数全部找出来。这句话中test_xxx 函数一定要以test_开头吗 def test_xxx 这种写法,正是严格遵守了 pytest 对测试函数/方法的命名要求
test_xxx 函数必须以 test_ 开头,这是 pytest 框架的默认强制规则。
pytest 就是靠这个命名规则来自动发现并执行测试用例的
也可以自定义在 项目的根目录下创建一个 pytest.ini 配置文件 中自定义
@pytest.mark.parametrize 介绍:
parametrize相当于for循环遍历吗?区别很大
@pytest.mark.parametrize 是 pytest 的"用例生成器"(Generator),而不是"用例执行器"。
它的运行时机:发生在 pytest 收集用例阶段(也就是你之前问的 run.py 跳转到 pytest 内部后,正式跑代码之前)。
它的工作:把你写的 1 个函数,根据传入的列表长度,动态克隆出 N 个独立的测试函数对象
场景 A:使用 for 循环
python
def test_for_loop():
data_list = 1, 2, 3
for data in data_list:
assert data > 0 # 假设第2个数据失败了
print(f"检查完 {data}")
执行结果:当循环到 data=2 时断言失败,程序直接崩溃终止,后面的 data=3 根本不会执行,也不会被打印。
报告显示:你只会看到 1 条测试用例,状态是"失败"
场景 B:使用 @pytest.mark.parametrize(正确做法)
python
@pytest.mark.parametrize('data', 1, 2, 3)
def test_parametrize(data):
assert data > 0
print(f"检查完 {data}")
执行结果:即使 data=2 失败了,data=3 依然会继续执行。
报告显示:你会看到 3 条独立的测试用例,比如 test_parametrize1 通过,test_parametrize2 失败,test_parametrize3 通过。
你用 parametrize:pytest 会把 YAML 里的 10 条接口数据变成 10 个独立的测试用例。即使第 3 个接口报 500 错误,第 4 个接口依然会正常执行。而且在 Allure 报告里,你能清晰地看到 10 行结果,每行对应一个接口,而不是笼统的 1 行。