宁夏企业网站建设,深圳做手机网站设计,制造网,宿迁网站建设推广前言 pytest装饰器是在使用 pytest 测试框架时用于扩展测试功能的特殊注解或修饰符。使用装饰器可以为测试函数提供额外的功能或行为。 以下是 pytest 装饰器的一些常见用法和用途#xff1a;
装饰器作用pytest.fixture用于定义测试用例的前置条件和后置操作。可以创建可重…前言 pytest装饰器是在使用 pytest 测试框架时用于扩展测试功能的特殊注解或修饰符。使用装饰器可以为测试函数提供额外的功能或行为。 以下是 pytest 装饰器的一些常见用法和用途
装饰器作用pytest.fixture用于定义测试用例的前置条件和后置操作。可以创建可重用的测试环境或共享资源并将其注入到测试函数中。通常fixture 可以返回所需的对象或执行特定的设置和清理操作。pytest.mark.parametrize用于参数化测试函数。通过在装饰的函数上提供参数列表可以运行多组具有不同输入的测试用例。这样可以轻松地扩展测试范围并减少重复的测试代码。pytest.mark.skip使用这个装饰器可以跳过不需要运行的测试用例。可以附带参数来提供跳过测试的原因或条件。pytest.mark.skipif类似于 pytest.mark.skip这个装饰器可以基于条件来跳过特定的测试用例。可以使用预定义的环境变量、Python 版本、操作系统等作为条件。pytest.mark.xfail这个装饰器标记所装饰的测试用例为 “expected failure”预期失败。也就是说预计在某些条件下测试将失败如果出现预期的失败将被视为测试通过如果测试用例没有失败则会被标记为测试失败。pytest.mark.repeat这个装饰器用于将测试用例重复运行多次。可以指定重复次数来确定运行次数。pytest.mark.usefixtures使用此装饰器可以在测试函数中直接使用已定义的 fixture而无需在函数签名中显式声明。这样可以简化测试函数的编写。pytest.mark.dependency用于声明测试用例之间的依赖关系以确保测试用例按正确的顺序执行。
一、pytest.fixture装饰器 常用的参数列表及其简要说明
参数说明scope指定fixture的作用域控制fixture的生命周期。可选值包括function默认值每个测试函数调用一次“class”每个测试类调用一次“module”每个模块调用一次或session整个测试会话过程中调用一次params为fixture指定不同的参数化值。可以是列表、元组或生成器。autouse控制fixture是否自动应用于测试用例。如果将其设置为True则fixture将自动应用于所有使用它的测试用例。ids为参数化fixture中的每个参数指定一个名称或标识符列表以便在测试报告中更好地识别不同的参数。name为fixture指定一个显示名称用于在测试报告中更好地标识fixture。
import pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
import time# pytest.fixture 声明这是一个夹具
# scopefunction 指定了夹具的作用域为函数级别也就是每个测试函数都会调用该夹具
# autouseTrue 指定夹具为自动使用的也就是不需要在测试函数中显式地调用夹具它会自动应用于每个测试函数
pytest.fixture(scopefunction, autouseTrue)
def setup_browser():设置和关闭浏览器的测试夹具driver webdriver.Chrome() # 初始化Chrome浏览器驱动driver.get(https://www.baidu.com/) # 打开百度首页yield driver # 返回driver对象供测试使用driver.quit() # 测试结束后关闭浏览器# pytest.fixture 声明这是一个夹具
# params[(csdn......)] 设置夹具的参数列表夹具被参数化为两个元组每个元组包含两个值表示不同的搜索引擎关键字和期望结果
# namesearch_engine 给夹具指定一个名字这样在测试函数中可以引用该夹具
# ids[CSDN, Baidu Knowledge] 为每个参数设置一个标识符这些标识符在测试报告中将用于标识参数化的实例
pytest.fixture(params[(csdn, CSDN - 专业开发者社区), (百度知识, 百度知道 - 全球领先中文互动问答平台)],namesearch_engine,ids[CSDN, Baidu Knowledge])
def parametrize_search_engine(request):参数化的搜索引擎测试夹具return request.param # 返回包含关键字和期望结果的元组def test_search_home_page(setup_browser):测试在百度首页搜索功能assert 百度一下 in setup_browser.page_source # 检查页面源代码中是否包含百度一下def test_navigation(setup_browser, search_engine):测试导航功能包括输入关键字搜索并选择第一个结果driver setup_browser # 获取浏览器驱动对象keyword, engine search_engine # 解包含有关键字和期望结果的元组# 输入指定关键字例如csdn或百度知识driver.find_element(By.CSS_SELECTOR, #kw).send_keys(keyword)# 点击搜索按钮driver.find_element(By.CSS_SELECTOR, [classbg s_btn]).click()time.sleep(5)# 选择搜索结果中的第一个链接进行点击driver.find_element(By.CSS_SELECTOR, [classresult c-container xpath-log new-pmd] h3 a).click()time.sleep(5)# 切换到最新窗口的句柄driver.switch_to.window(driver.window_handles[-1])assert driver.title engine # 检查打开的页面标题是否与期望结果一致def test_autouse_fixture():测试autouseTrue是否生效assert 1 1if __name__ __main__:pytest.main([test_run.py, -v])
二、pytest.mark.parametrize装饰器
import pytest# pytest.mark.parametrize装饰器定义了一个参数化测试函数,允许我们一次运行多组数据进行测试
# 以下参数列表中的每个数据组都将分别传递给被装饰的测试函数
# 参数化允许我们在不同的输入值之间进行测试以确保代码在各种情况下都能正常工作
pytest.mark.parametrize(a, b, expected, [(2, 3, 5), # 测试用例1当a2b3时预期的输出结果应为5(4, 5, 9), # 测试用例2当a4b5时预期的输出结果应为9(6, 7, 13) # 测试用例3当a6b7时预期的输出结果应为13
])
def test_addition(a, b, expected):# 断言语句用于检查表达式是否为真以验证代码的正确性# 如果表达式为False则会引发AssertionError异常。assert a b expected # 检查a b是否等于预期的输出结果# pytest.main()函数被调用来运行测试
# 运行名为test_run.py的测试文件并通过-v参数显示每个测试用例的执行结果
if __name__ __main__:pytest.main([test_run.py, -v])三、pytest.mark.skip装饰器
import pytest# 该测试用例标记为 pytest.mark.skip 装饰器表示该测试尚未实现应跳过执行
# 跳过的原因被指定为 尚未实现这通常用于临时禁用尚未准备好或需要进一步开发的测试
pytest.mark.skip(reasonNot implemented yet)
def test_multiply():assert 3 * 4 12if __name__ __main__:pytest.main([test_run.py, -v])四、pytest.mark.skipif装饰器
import pytest
import platform# 使用 pytest.mark.skipif 装饰器为测试用例添加条件跳过的标记pytest.mark.skipif(platform.system() Windowsand platform.release() 10,reason跳过 Windows 10 版本的测试用例)
def test_linux_run():# 仅在 Linux 系统下运行的测试代码assert 2 2pytest.mark.skipif(platform.system() Linux,reason跳过在 Linux 系统下运行的测试用例)
def test_windows_run():# 仅在 Windows 系统下运行的测试代码assert 2 2if __name__ __main__:pytest.main([test_run.py, -v]) 五、pytest.mark.xfail装饰器
import pytest# pytest.mark.xfail 是Pytest测试框架中的一个装饰器用于标记预期测试失败的测试用例
# 预期失败的测试用例因为除以零会引发异常
pytest.mark.xfail
def test_division():assert 1 / 0 2# 预期失败的测试用例因为除以零不等于1并且应该引发 ZeroDivisionError 异常
pytest.mark.xfail(raisesZeroDivisionError)
def test_division_zero():assert 1 / 0 1# 预期失败的测试用例已知此加法操作会失败
pytest.mark.xfail(reasonThis test is known to fail)
def test_addition():assert 2 2 5# 预期失败的测试用例这个测试实际上是正确的但我们使用 xfail 标记将其标记为预期失败
pytest.mark.xfail
def test_actually_correct():assert 1 1 2if __name__ __main__:pytest.main([test_run.py, -v])六、pytest.mark.repeat装饰器
# pip install pytest-repeat 安装扩展插件
import pytest# pytest.mark.repeat 是 Pytest 测试框架中的一个装饰器用于指定一个测试用例的重复运行次数
# 将该测试用例重复执行3次
pytest.mark.repeat(3)
def test_addition():result 2 2assert result 4if __name__ __main__:pytest.main([test_run.py, -v])七、pytest.mark.usefixtures装饰器
import pytestpytest.fixture
def setup_data():前置条件 - 准备测试数据print(前置条件--准备测试数据)data test datayield dataprint(后置条件--清理测试数据)def test_example(setup_data):示例测试方法使用了前置条件 fixture setup_datadata setup_dataprint(执行示例测试)assert data test datapytest.mark.usefixtures(setup_data)
def test_method():方法测试使用了前置条件 fixture setup_data但不接收它作为参数print(执行方法测试)assert 1 1 2if __name__ __main__:pytest.main([test_run.py, -s])定义了两个测试函数test_example和test_method它们都使用了名为setup_data的 fixture 作为测试的前置条件在test_example中setup_data fixture 被作为测试函数的参数使用。在函数内部data变量被赋值为setup_data fixture 返回的值然后用于测试在test_method中使用了pytest.mark.usefixtures装饰器并将setup_data作为参数传递。这样一来setup_data fixture 的前置条件将在运行test_method之前自动执行。虽然在函数体内没有显式接收setup_data作为参数但仍可以通过setup_data执行相关操作。这两种写法分别适用于需要测试数据作为输入和不依赖测试数据作为输入的情况
八、pytest.mark.dependency装饰器
# pip install pytest-dependency 安装扩展插件
import pytestpytest.mark.dependency()
def test_login():# 登录测试assert True# 指定 test_login 为依赖
pytest.mark.dependency(depends[test_login])
def test_search():# 搜索测试assert True# 指定 test_login 和 test_search 为依赖
pytest.mark.dependency(depends[test_login, test_search])
def test_checkout():# 结账测试assert Trueif __name__ __main__:pytest.main([test_run.py, -v])test_login 测试函数没有指定任何依赖关系test_search 测试函数指定了 test_login 作为依赖因此在运行 test_search 之前会先运行 test_logintest_checkout 测试函数指定了 test_login 和 test_search 作为依赖因此在运行test_checkout 之前会先运行 test_login 和 test_search这样可以确保测试按正确的顺序运行并且测试之间的依赖关系得到满足。如果某个测试的依赖失败那么依赖它的测试也将被跳过执行
九、自定义装饰器
import pytest# 定义一个自定义装饰器用于对测试用例进行分组
pytest.mark.group1
def test_addition():assert (1 2) 3# 定义第二个分组
pytest.mark.group1
def test_subtraction():assert (5 - 3) 2# 定义第三个分组
pytest.mark.group2
def test_multiplication():assert (2 * 3) 6# 定义第四个分组
pytest.mark.group2
def test_division():assert (10 / 2) 5# 如果当前文件被直接执行而不是被导入为模块则执行以下代码
if __name__ __main__:# 运行 Pytest 并指定只运行属于 group1 分组的测试用例pytest.main([test_run.py, -m, group1])通过使用 pytest.mark.group1 和 pytest.mark.group2装饰器我们可以将测试用例进行逻辑分组。这样做的好处是可以只运行特定分组的测试用例而不是运行所有测试用例在上述代码中test_addition() 和 test_subtraction() 被分组为’group1’test_multiplication() 和 test_division() 被分组为 ‘group2’运行以上示例会有警告信息这时我们需要把group1 和group2 注册到 pytest中在项目目录中创建一个pytest.ini如果你尚未创建并在其中定义自定义标记。下面是在pytest.ini 中注册group1和group2 标记的示例
[pytest]
markers group1: group1 测试的描述group2: group2 测试的描述