Pytest学习教程_装饰器(二)

前言

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 声明这是一个夹具
# scope="function" 指定了夹具的作用域为函数级别,也就是每个测试函数都会调用该夹具
# autouse=True 指定夹具为自动使用的,也就是不需要在测试函数中显式地调用夹具,它会自动应用于每个测试函数
@pytest.fixture(scope="function", autouse=True)
def setup_browser():"""设置和关闭浏览器的测试夹具"""driver = webdriver.Chrome()  # 初始化Chrome浏览器驱动driver.get("https://www.baidu.com/")  # 打开百度首页yield driver  # 返回driver对象供测试使用driver.quit()  # 测试结束后关闭浏览器# @pytest.fixture 声明这是一个夹具
# params=[("csdn"......)] 设置夹具的参数列表,夹具被参数化为两个元组,每个元组包含两个值,表示不同的搜索引擎关键字和期望结果
# name="search_engine" 给夹具指定一个名字,这样在测试函数中可以引用该夹具
# ids=["CSDN", "Baidu Knowledge"] 为每个参数设置一个标识符,这些标识符在测试报告中将用于标识参数化的实例
@pytest.fixture(params=[("csdn", "CSDN - 专业开发者社区"), ("百度知识", "百度知道 - 全球领先中文互动问答平台")],name="search_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, '[class="bg s_btn"]').click()time.sleep(5)# 选择搜索结果中的第一个链接进行点击driver.find_element(By.CSS_SELECTOR, '[class="result 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():"""测试autouse=True是否生效"""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:当a=2,b=3时,预期的输出结果应为5(4, 5, 9),  # 测试用例2:当a=4,b=5时,预期的输出结果应为9(6, 7, 13)  # 测试用例3:当a=6,b=7时,预期的输出结果应为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(reason="Not 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() == "Windows"and platform.release() == "10",reason="跳过 Windows 10 版本的测试用例")
def test_linux_run():# 仅在 Linux 系统下运行的测试代码assert 2 == 2@pytest.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(raises=ZeroDivisionError)
def test_division_zero():assert 1 / 0 == 1# 预期失败的测试用例,已知此加法操作会失败
@pytest.mark.xfail(reason="This 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 pytest@pytest.fixture
def setup_data():"""前置条件 - 准备测试数据"""print("前置条件-->准备测试数据")data = "test data"yield dataprint("后置条件-->清理测试数据")def test_example(setup_data):"""示例测试方法,使用了前置条件 fixture 'setup_data'"""data = setup_dataprint("执行示例测试")assert data == "test data"@pytest.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 pytest@pytest.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_login
  • test_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 测试的描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/21227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

理解树的结构

树的重要性 二分查找算法、几种核心的排序算法以及图算法都与树有非常密切的关系。有句话锁,“没学会树,算法相当于白学”,可见,树在算法中的地位。 树的考察方面 层次遍历以及拓展问题 前后序遍历与拓展问题 中序遍历与搜索树问…

Ubuntu网络设置之固定IP详解

尊敬的家人们,欢迎观看我的文章!今天,我们将为您介绍Ubuntu22.04操作系统中固定IP的设置方法,帮助您更好地管理网络连接并提高网络稳定性。 什么是固定IP? 在网络中,IP地址是设备在网络上的唯一标识。通常…

通过华为杯竞赛、高教社杯和数学建模国赛实现逆袭;助力名利双收

文章目录 ⭐ 赛事介绍⭐ 参赛好处⭐ 辅导比赛⭐ 写在最后 ⭐ 赛事介绍 华为杯全国研究生数学建模竞赛是由华为公司主办的一项面向全国研究生的数学建模竞赛。该竞赛旨在通过实际问题的建模和解决,培养研究生的创新能力和团队合作精神,推动科技创新和应用…

长相思追剧小游戏

看效果图 Vue长相思 刚学Vue&#xff0c;正好在追剧&#xff0c;看到这个小案例觉得挺好玩的&#xff0c;第一天学&#xff0c;代码太简陋了 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name&qu…

复亚智能打造全新云平台:让无人机任务管理更智能、更简单

复亚智能全新升级的MindView云平台&#xff0c;对航线规划、任务管理、自动飞行、数据管理等各个环节开展可视化、数字化、智能化监管&#xff0c;从任务到结果的“看得清”、“管得住”、“查得准”&#xff0c;带来更轻松的操作&#xff0c;改善作业效率、安全保障和用户体验…

动态IP代理的工作原理

动态IP代理在现今的网络环境中扮演着重要角色。它不仅能够帮助用户绕过网站的访问限制和封锁&#xff0c;还可以保护用户的隐私和匿名性。本文将深入分析动态IP代理的工作原理&#xff0c;解释其关键要素&#xff0c;并探讨其在现代网络中的应用。 在互联网时代&#xff0c;随着…

GaussDB数据库的元数据及其管理简介

目录 一、前言 二、元数据简介 1、元数据定义 2、元数据分类 3、数据库元数据管理 三、GaussDB数据库的元数据管理 1、GaussDB数据库的元数据管理 2、通过“SQL 系统表/系统视图/系统函数”的方式管理&#xff08;采集&#xff09;元数据 1&#xff09;获取表、视图及…

flutter开发实战-实现css线性渐变转换flutter渐变LinearGradient功能

flutter开发实战-实现css线性渐变转换flutter渐变LinearGradient功能 在之前项目开发中&#xff0c;遇到更换样式&#xff0c;由于从服务器端获取的样式均为css属性值&#xff0c;需要将其转换成flutter类对应的属性值。这里只处理线性渐变linear-gradient 比如渐变 “linear-…

【Linux操作系统】网络配置详解:从原理到实践(详细通俗讲明DNS)

导语&#xff1a;网络配置是Linux系统中的一项重要任务&#xff0c;合理的网络配置可以保证计算机与其他设备的正常通信。本文将详细介绍Linux网络配置的原理和实践&#xff0c;包括网络配置原理、查看网络IP和网关、测试网络连通性、网络环境配置、设置主机名和hosts映射以及主…

win10笔记本显示器根据页面显示亮度自动调节亮度的问题

系统是win10企业版&#xff0c;针对这个问题查了很多种方法&#xff0c;比如&#xff1a; 1、控制面板->硬件和声音->电源选项->点击当前电源计划的更改计划设置->更改高级电源设置->显示->启用自适应亮度 但是我发现我的电源计划只有平衡这一种&#xff0c…

申请科技型中小企业的好处有哪些?

科技型中小企业&#xff0c;这是由国家出台的&#xff0c;科技部认定的&#xff0c;对中小型企业的一种荣誉。这种企业是有一定数量的科技人员从事科技研究开发&#xff0c;有了一定成果并转化为高新技术产品或服务&#xff0c;实现可持续发展的中小企业。 申请科技型中小企业有…

【雕爷学编程】 MicroPython动手做(38)——控制触摸屏

MixPY——让爱(AI)触手可及 MixPY布局 主控芯片&#xff1a;K210&#xff08;64位双核带硬件FPU和卷积加速器的 RISC-V CPU&#xff09; 显示屏&#xff1a;LCD_2.8寸 320*240分辨率&#xff0c;支持电阻触摸 摄像头&#xff1a;OV2640&#xff0c;200W像素 扬声器&#…

【Golang 接口自动化08】使用标准库httptest完成HTTP请求的Mock测试

目录 前言 http包的HandleFunc函数 http.Request/http.ResponseWriter httptest 定义被测接口 测试代码 测试执行 总结 资料获取方法 前言 Mock是一个做自动化测试永远绕不过去的话题。本文主要介绍使用标准库net/http/httptest完成HTTP请求的Mock的测试方法。 可能有…

【安装】阿里云轻量服务器安装Ubuntu图形化界面(端口号/灰屏问题)

阿里云官网链接 https://help.aliyun.com/zh/simple-application-server/use-cases/use-vnc-to-build-guis-on-ubuntu-18-04-and-20-04 网上搜了很多教程&#xff0c;但是我没在界面看到有vnc连接&#xff0c;后面才发现官网有教程。 其实官网很详细了&#xff0c;不过这里还是…

题解 | #1001.Count# 2023杭电暑期多校6

1001.Count 签到 题目大意 给定 n , m , k n,m,k n,m,k &#xff0c;构造长度为 n n n 的整数序列&#xff0c;元素大小范围为 a i ∈ [ 1 , m ] a_i\in [1,m] ai​∈[1,m] &#xff0c;并且需要保证前 k k k 个元素和后 k k k 个元素对应相同 求可以构造出的序列数量 …

Flink Windows(窗口)详解

Windows&#xff08;窗口&#xff09; Windows是流计算的核心。Windows将流分成有限大小的“buckets”&#xff0c;我们可以在其上应用聚合计算&#xff08;ProcessWindowFunction&#xff0c;ReduceFunction&#xff0c;AggregateFunction或FoldFunction&#xff09;等。在Fl…

【java安全】无Commons-Collections的Shiro550反序列化利用

文章目录 【java安全】无Commons-Collections的Shiro550反序列化利用Shiro550利用的难点CommonsBeanutils1是否可以Shiro中&#xff1f;什么是serialVersionUID&#xff1f;W 无依赖的Shiro反序列化利用链POC 【java安全】无Commons-Collections的Shiro550反序列化利用 Shiro5…

整数拆分——力扣343

文章目录 题目描述法一 动态规划法二 动态规划优化法三 数学 题目描述 法一 动态规划 int integerBreak(int n) {vector<int> dp(n1);for(int i2;i<n;i){int curMax 0;for(int j1;j<i;j){curMax max(curMax, max(j*(i-j), j*dp[i-j]));}dp[i] curMax;} return d…

AI赋能转型升级 助力打造“数智辽宁”——首次大模型研讨沙龙在沈成功举行

当前&#xff0c;以“ChatGPT”为代表的大模型正在引领新一轮全球人工智能技术发展浪潮&#xff0c;推动人工智能从以专用小模型定制训练为主的“手工作坊时代”&#xff0c;迈入以通用大模型预训练为主的“工业化时代”&#xff0c;正不断加速实体经济智能化升级&#xff0c;深…

量子机器学习解决方案新鲜出炉!Rigetti和ADIALab签署合作

​ &#xff08;图片来源&#xff1a;网络&#xff09; 近日&#xff0c;美国全栈量子经典计算的先驱Rigetti Computing宣布与阿拉伯联合酋长国的ADIA Lab签署了合作协议&#xff0c;双方将共同设计、构建、运行和优化量子计算解决方案&#xff0c;旨在解决概率分布分类问题&am…