Pytest测试框架2

目录:

  1. pytest参数化用例
  2. pytest标记测试用例
  3. pytest设置跳过、预期失败用例
  4. pytest运行用例
  5. pytest测试用例调度与运行
  6. pytest命令行常用参数
  7. python执行pytest
  8. pytest异常处理

1.pytest参数化用例

参数化

  • 通过参数的方式传递数据,从而实现数据和脚本分离。
  • 并且可以实现用例的重复生成与执行。

参数化应用场景

  • 测试登录场景
    • 测试登录成功,登录失败(账号错误,密码错误)
    • 创建多种账号: 中⽂文账号,英⽂文账号
  • 普通测试用例方法
    • Copy 多份代码 or 读⼊入参数?
    • 一次性执⾏多个输⼊入参数
def test_param_login_ok():
    # 登录成功
    username = "right"
    password = "right"
    login(username,password)

def test_param_login_fail():
    # 登录失败
    username = "wrong"
    password = "wrong"
    login(username,password)

参数化实现方案 

  • pytest 参数化实现方法
  • 装饰器:@pytest.mark.parametrize
@pytest.mark.parametrize("username,password", [["right", "right"], ["wrong", "wrong"]])
def test_param(username, password):
    login(username, password)

Mark:参数化测试函数使用

  • 单参数
  • 多参数
  • 用例重命名
  • 笛卡尔积

参数化:单参数情况

  • 单参数,可以将数据放在列表中
search_list = ['appium', 'selenium', 'pytest']

@pytest.mark.parametrize('name', search_list)
def test_search(name):
    assert name in search_list

 示例:

import pytest

search_list = ['appium', 'selenium', 'pytest']

@pytest.mark.parametrize("search_key", ['appium', 'selenium', 'pytest', "", 'requests', 'abc'])
def test_search_param(search_key):
    assert search_key in search_list

参数化:多参数情况

  • 将数据放在列表嵌套元组中
  • 将数据放在列表嵌套列表中
import pytest

# 数据放在元组中
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+5", 7), ("7+5", 12)])
def test_mark_more(test_input, expected):
    assert eval(test_input) == expected


# 数据放在列表中
@pytest.mark.parametrize("test_input,expected", [["3+5", 8], ["2+5", 7], ["7+5", 12]])
def test_mark_more(test_input, expected):
    assert eval(test_input) == expected

参数化:用例重命名-添加 ids 参数

  • 通过ids参数,将别名放在列表中
import pytest


@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+5", 7), ("7+5", 12)],
                         ids=['add_3+5=8', 'add_2+5=7', 'add_3+5=12'])
def test_mark_more(test_input, expected):
    assert eval(test_input) == expected

 参数化:用例重命名-添加 ids 参数(中文)

# 创建conftest.py 文件 ,将下面内容添加进去,运行脚本
def pytest_collection_modifyitems(items):
    """
    测试用例收集完成时,将收集到的用例名name和用例标识nodeid的中文信息显示在控制台上
    """
    for i in items:
        i.name=i.name.encode("utf-8").decode("unicode_escape")
        i._nodeid=i.nodeid.encode("utf-8").decode("unicode_escape")
@pytest.mark.parametrize("test_input,expected",[
    ("3+5",8),("2+5",7),("7+5",12)
],ids=["3和5相加","2和5相加","7和5相加"])
def test_mark_more(test_input,expected):
    assert eval(test_input) == expected

参数化:笛卡尔积

  • 两组数据
    • a=[1,2,3]
    • b=[a,b,c]
  • 对应有几种组合形势 ?
    • (1,a),(1,b),(1,c)
    • (2,a),(2,b),(2,c)
    • (3,a),(3,b),(3,c)
import pytest

@pytest.mark.parametrize("b", ["a", "b", "c"])
@pytest.mark.parametrize("a", [1, 2, 3])
def test_param1(a, b):
    print(f"笛卡积形式的参数化中 a={a} , b={b}")

2.pytest标记测试用例

Mark:标记测试用例

  • 场景:只执行符合要求的某一部分用例 可以把一个web项目划分多个模块,然后指定模块名称执行。
  • 解决: 在测试用例方法上加 @pytest.mark.标签名
  • 执行: -m 执行自定义标记的相关用例
    • pytest -s test_mark_zi_09.py -m=webtest
    • pytest -s test_mark_zi_09.py -m apptest
    • pytest -s test_mark_zi_09.py -m "not ios"
import pytest

def double(a):
    return a * 2

@pytest.mark.int
def test_double_int():
    print('test double int')
    assert 2 == double(1)

@pytest.mark.minus
def test_double_minus():
    print('test double minus')
    assert -2 == double(-1)

@pytest.mark.float
def test_double_float():
    assert 0.2 == double(0.1)

@pytest.mark.float
def test_double2_float():
    assert -10.2 == double(-0.1)

@pytest.mark.zero
def test_double_0():
    assert 10 == double(0)

@pytest.mark.bignum
def test_double_bignum():
    assert 200 == double(100)

@pytest.mark.str
def test_double_str():
    assert 'aa' == double('a')

@pytest.mark.str
def test_double_str():
    assert 'a$a$' == double('a$')

在终端运行命令: 

pytest test_test1.py -v -s -m "str"

上述代码会出现异常,pytest识别不到这些标签,解决办法如下:

在项目根目录新建一个pytest.ini文件

重新运行:

  

3.pytest设置跳过、预期失败用例

Mark:跳过(Skip)及预期失败(xFail)

  • 这是 pytest 的内置标签,可以处理一些特殊的测试用例,不能成功的测试用例
  • skip - 始终跳过该测试用例
  • skipif - 遇到特定情况跳过该测试用例
  • xfail - 遇到特定情况,产生一个“期望失败”输出

Skip 使用场景

  • 调试时不想运行这个用例
  • 标记无法在某些平台上运行的测试功能
  • 在某些版本中执行,其他版本中跳过
  • 比如:当前的外部资源不可用时跳过
    • 如果测试数据是从数据库中取到的,
    • 连接数据库的功能如果返回结果未成功就跳过,因为执行也都报错
  • 解决 1:添加装饰器
    • @pytest.mark.skip
    • @pytest.mark.skipif
  • 解决 2:代码中添加跳过代码
    • pytest.skip(reason)
import sys
import pytest

@pytest.mark.skip
def test_aaa():
    print("没有任何输出")
    assert True

@pytest.mark.skip(reason="代码没有实现")
def test_bbb():
    assert False

@pytest.mark.skipif(sys.platform == 'darwin', reason="does now run on mac")
def test_case1():
    assert True

@pytest.mark.skipif(sys.platform == 'win', reason="dose not run on windows")
def test_case2():
    assert True

@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher")
def test_case3():
    assert True

def check_login():
    # return True
    return False

def test_ccc():
    if not check_login():
        pytest.skip("")
    print("end")

xfail 使用场景

  • 与 skip 类似 ,预期结果为 fail ,标记用例为 fail
  • 用法:添加装饰器@pytest.mark.xfail
  • xfail 是 pytest 中的一个标记,用于标记测试用例,表示该测试用例在某些条件下不会执行,而是被标记为 pass。通常用于在开发阶段快速验证代码的正确性,而在发布版本中禁用这些测试用例,以避免潜在的问题。使用 xfail 标记的测试用例在运行时会被 pytest 忽略,但它们仍然会被计入测试覆盖率。这使得您可以快速查看哪些测试用例未通过,而无需查看未通过的原因。

import pytest

@pytest.mark.xfail
def test_aaa():
    print('test_xfail 方法执行')
    # assert 1 == 2
    assert 2 == 2

xfail = pytest.mark.xfail

@xfail(reason="有bug")
def test_hello():
    assert 0

def test_xfail():
    print('****开始测试****')
    pytest.xfail(reason='该功能尚未完成')
    print('测试过程')
    assert 1 == 1

4.pytest运行用例

运行多条用例

  • 运行 某个/多个 用例包
  • 运行 某个/多个 用例模块
  • 运行 某个/多个 用例类
  • 运行 某个/多个 用例方法

运行多条用例方式

  • 执行包下所有的用例:pytest [包名]
  • 执行单独一个 pytest 模块:pytest 文件名.py
  • 运行某个模块里面某个类:pytest 文件名.py::类名
  • 运行某个模块里面某个类里面的方法:pytest 文件名.py::类名::方法名

 运行结果分析

  • 常用的:fail/error/pass
  • 特殊的结果:warning/deselect

运行结果分析是测试执行过程中非常重要的一个环节,可以帮助开发人员快速定位和解决问题。常用的结果包括:

  • fail:测试用例失败,即预期结果和实际结果不一致。
  • error:测试用例执行过程中发生错误,导致测试用例无法继续执行。
  • pass:测试用例通过,即预期结果和实际结果一致。

除了常用的结果之外,还有一些特殊的结果,例如:

  • warning:测试用例执行过程中出现警告,但测试用例仍然通过。
  • deselect:测试用例被标记为跳过,即测试用例被排除在测试执行之外。

5.pytest测试用例调度与运行

命令行参数-使用缓存状态

  • --lf(--last-failed) 选项会重新运行上一次失败的测试用例。它会跳过所有未失败的测试用例,只运行上一次失败的测试用例。
  • --ff(--failed-first) 选项会先运行上一次失败的测试用例,然后再运行其余的测试用例。它会跳过所有未失败的测试用例,先运行上一次失败的测试用例,然后再运行其余的测试用例。

6.pytest命令行常用参数

--help 
-x   用例一旦失败(fail/error),就立刻停止执行
--maxfail=num 用例达到
-m  标记用例
-k  执行包含某个关键字的测试用例
-v 打印详细日志
-s 打印输出日志(一般-vs一块儿使用)
--collect-only(测试平台,pytest 自动导入功能 )

 

  • -x 参数用于设置 pytest 执行行为,一旦有测试用例失败,就会立刻停止执行。这对于调试测试用例非常有用,可以快速定位和修复问题。
  • --maxfail=num 参数用于设置 pytest 执行的最大失败次数。当一个测试用例失败时,pytest 会自动跳过所有未失败的测试用例,只运行上一次失败的测试用例。如果一个测试用例执行次数达到 maxfail 次,pytest 就会停止执行。
  • -m 参数用于标记测试用例。通过指定 -m 参数,可以过滤掉不符合条件的测试用例,只运行符合条件的测试用例。
  • -k 参数用于执行包含某个关键字的测试用例。通过指定 -k 参数,可以过滤掉不符合关键字的测试用例,只运行包含关键字的测试用例。
  • -v 参数用于打印详细日志。在执行测试用例时,pytest 会记录每个测试用例的详细信息,包括测试用例的名称、执行时间、返回值等。通过指定 -v 参数,可以查看这些详细信息。
  • -s 参数用于打印输出日志。在执行测试用例时,pytest 会记录每个测试用例的输出信息。通过指定 -s 参数,可以查看这些输出信息。
  • --collect-only 参数用于设置 pytest 的自动导入功能。在执行 pytest 时,它会自动导入所有测试文件中的模块和类,并生成相应的测试用例。通过指定 --collect-only 参数,可以只执行自动导入功能,而不执行实际的测试用例。

7.python执行pytest

Python 代码执行 pytest

  • 使用 main 函数
  • 使用 python -m pytest 调用 pytest(jenkins 持续集成用到)

Python 代码执行 pytest - main 函数

if __name__ == '__main__':
    # 1、运行当前目录下所有符合规则的用例,包括子目录(test_*.py 和 *_test.py)
    pytest.main()
    # 2、运行test_mark1.py::test_dkej模块中的某一条用例
    pytest.main(['test_mark1.py::test_dkej','-vs'])
    # 3、运行某个 标签
    pytest.main(['test_mark1.py','-vs','-m','dkej'])

运行方式(在终端输入命令~)
  `python test_*.py `

8.pytest异常处理

常用的异常处理方法

  • try…except
  • pytest.raises()

异常处理方法 try …except

try:
    可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
    处理异常的代码块1
except [ (Error3, Error4, ... ) [as e] ]:
    处理异常的代码块2
except  [Exception]:
    处理其它异常
try:
    a = int(input('输入被除数:'))
    b = int(input('输入除数:'))
    c = a / b
    print('您输入的俩个数相除的结果是:', c)
except(ValueError, ArithmeticError):
    print('程序发生数字格式异常,算术异常之一')
except:
    print('未知异常')
print('程序继续运行')

异常处理方法 pytest.raise()

  • 可以捕获特定的异常
  • 获取捕获的异常的细节(异常类型,异常信息)
  • 发生异常,后面的代码将不会被执行

pytest.raise() 用法

def test_raise():
    with pytest.raises(ValueError, match='must be 0 or None'):
        raise ValueError("value must be 0 or None")

def test_raise1():
    with pytest.raises(ValueError) as exc_info:
        raise ValueError("value must be 42")
    assert exc_info.type is ValueError
    assert exc_info.value.args[0] == "value must be 42"

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

并网逆变器学习笔记6---三电平SVPWM下的连续和不连续调制

之前在学习中总结过一次DPWM策略选择&#xff1a;并网逆变器学习笔记5---三电平DPWM 但是对于三电平逆变器而言&#xff0c;如何从连续调制切换到不连续调制&#xff0c;存在一些疑惑点&#xff0c;下午闲来无事&#xff0c;把SVPWM下的连续调制和不连续调制的开关状态选择&am…

MyCat核心概念、需求案例讲解、环境准备及分片配置

1.MyCat概念介绍 2.MyCat入门需求 2.1 需求分析 2.2 环境准备 输入以下命令检查服务器防火墙状态 dead代表关闭状态&#xff0c;如果不关闭也可以需要开放特定的端口号&#xff01;&#xff01; systemctl status firewalld接着需要在三台服务器上的MySQL上创建三个数据库db0…

(树) 剑指 Offer 36. 二叉搜索树与双向链表 ——【Leetcode每日一题】

❓ 剑指 Offer 36. 二叉搜索树与双向链表 难度&#xff1a;中等 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个 排序的循环双向链表。要求不能创建任何新的节点&#xff0c;只能调整树中节点指针的指向。 为了让您更好地理解问题&#xff0c;以下面的二叉搜索树为…

相机传感器格式与镜头光圈参数

相机靶面大小 CCD/CMOS图像传感器尺寸&#xff08;sensor format&#xff09;1/2’‘、1/3’‘、1/4’实际是多大 1英寸——靶面尺寸为宽12.7mm*高9.6mm&#xff0c;对角线16mm。 2/3英寸——靶面尺寸为宽8.8mm*高6.6mm&#xff0c;对角线11mm。 1/2英寸——靶面尺寸为宽6.…

SSE技术和WebSocket技术实现即时通讯

文章目录 一、SSE1.1 什么是SSE1.2 工作原理1.3 特点和适用场景1.4 API用法1.5 代码实现 二、WebSocket2.1 什么是WebSocket2.2 工作原理2.3 特点和适用场景2.4 API用法2.5 代码实现 三、SSE与WebSocket的比较 当涉及到实现实时通信的Web应用程序时&#xff0c;两种常见的技术选…

网络安全【黑客技术】自学

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成…

每天五分钟机器学习:梯度下降算法和正规方程的比较

本文重点 梯度下降算法和正规方程是两种常用的机器学习算法,用于求解线性回归问题。它们各自有一些优点和缺点,下面将分别对它们进行详细的讨论。 区别 1. 梯度下降算法是一种迭代的优化算法,通过不断迭代调整参数来逼近最优解。它的基本思想是根据目标函数的梯度方向,沿…

openGauss学习笔记-32 openGauss 高级数据管理-批处理模式

文章目录 openGauss学习笔记-32 openGauss 高级数据管理-批处理模式32.1 语法格式32.2 参数说明32.3 示例 openGauss学习笔记-32 openGauss 高级数据管理-批处理模式 openGauss支持从文本文件执行SQL语句。openGauss提供了gsql工具实现SQL语句的批量处理。 以下场景建议使用批…

测试人员简单使用Jenkins

一、测试人员使用jenkins干什么&#xff1f; 部署测试环境 二、相关配置说明 一般由开发人员进行具体配置 1.Repository URL&#xff1a;填写git地址 2.填写开发分支&#xff0c;测试人员可通过相应分支进行测试环境的构建部署 当多个版本并行时&#xff0c;开发人员可以通过…

【各个突破】Echart的象柱形图数值为0时,图像发生严重偏移,一招即可解决

【各个突破】Echart的象柱形图数值为0时&#xff0c;图像发生严重偏移&#xff0c;一招即可解决 1&#xff0c;问题描述2&#xff0c;解决方法3&#xff0c;最终结果 1&#xff0c;问题描述 当数值是0亩时&#xff0c;圆形图标发生位置偏移&#xff0c;据悉&#xff0c;该bug是…

掌握 JVM 调优命令

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ JVM 日常调优总结起来就是&#xff1a;首先通过 jps 命令查看当前进程&#xff0c;然后根据 pid 通过 jinfo 命令查看和修改 jvm 参数&#xff0c;通过 jstat 命令查看 cla…

漫画 | TCP/IP之大明邮差

后记&#xff1a; 1973年&#xff0c;卡恩与瑟夫开发出了网络中最核心的两个协议&#xff1a;TCP协议和IP协议&#xff0c;随后为了验证两个协议的可用性&#xff0c;他们做了一个实验&#xff0c;在多个异构网络中进行数据传输&#xff0c;数据包在经过近10万公里的旅程后到达…

git删除已经提交的大文件

当你不小心把一个巨大的二进制文件提交到git仓库的时候&#xff0c;此时删除再提交也没有用了&#xff0c;大文件已经在仓库中留底了。另外比如需要删除某个需要保密的文件&#xff0c;都是相同的解决办法。 我本来想着把dll放在三方库里面提交到仓库里&#xff0c;省得在不同…

STM32 低功耗-待机模式

STM32 待机模式 文章目录 STM32 待机模式第1章 低功耗模式简介第2章 待机模式简介2.1 进入待机模式2.1 退出待机模式 第3章 待机模式代码部分总结 第1章 低功耗模式简介 在 STM32 的正常工作中&#xff0c;具有四种工作模式&#xff1a;运行、睡眠、停止和待机模式。 在系统或…

【九】mybatis 缓存模块设计

mybatis 缓存模块设计 简介&#xff1a;MyBatis提供了一级缓存和二级缓存&#xff0c;其中一级缓存基于SqlSession实现&#xff0c;而二级缓存基于Mapper实现。这里我们就来学习一下MyBatis缓存的使用&#xff0c;并分析MyBatis缓存的实现原理。 首先我们找到缓存模块的源码&a…

EVE-NG MPLS L2VPN static lsp

目录 1 拓扑 2 配置步骤 2.1 配置接口IP 和路由协议 2.2 配置MPLS LDP 2.3 配置L2VPN PW 2.4 验证L2VPN 1 拓扑 2 配置步骤 2.1 配置接口IP 和路由协议 PE1 interface LoopBack 0ip address 1.1.1.9 32 quitinterface GigabitEthernet1/0ip address 10.1.1.1 255.255…

【腾讯云 Cloud Studio 实战训练营】基于Cloud Studio构建React完成点餐H5页面

前言 【腾讯云 Cloud Studio 实战训练营】基于Cloud Studio 构建React完成点餐H5页面一、Cloud Studio介绍1.1 Cloud Studio 是什么1.2 相关链接1.3 登录注册 二、实战练习2.1 初始化工作空间2.2 开发一个简版的点餐系统页面1. 安装 antd-mobile2. 安装 less 和 less-loader3. …

网络安全之原型链污染

目录&#xff1a; 目录&#xff1a; 一、概念 二、举例 三、 实操了解 总结 四、抛出原题&#xff0c;历年原题复现 第一题&#xff1a; 五、分析与原理 第二题&#xff1a; 八、分析与原理 九、具体操作&#xff0c;payload与结果 结果&#xff1a; 一、概念 Java…

C++ 派生类的拷贝构造函数

当存在类的继承关系时&#xff0c;对于一个类&#xff0c;如果程序员没有编写拷贝构造函数&#xff0c;编译系统会在必要时自动生成一个隐含的拷贝构造函数&#xff0c;这个隐含的拷贝构造函数会自动调用基类的拷贝构造函数&#xff0c;然后对派生类新增的成员对象一一执行拷贝…