Pytest框架测试

Pytest 是什么?

  • pytest 能够支持简单的单元测试和复杂的功能测试;
  • pytest 可以结合 Requests 实现接口测试; 结合 Selenium、Appium 实现自动化功能测试;
  • 使用 pytest 结合 Allure 集成到 Jenkins 中可以实现持续集成。
  • pytest 支持 315 种以上的插件;

为什么要选择 Pytest

  • 丰富的第三方插件
    • 报告
    • 多线程
    • 顺序控制

为什么要选择 Pytest

  • 简单灵活
  • # content of test_sample.py def inc(x):
  • return x + 1
  • def test_answer():
  • assert inc(3) == 5

为什么要选择 Pytest

  • 兼容 unittest
  • 定制化插件开发

Pytest 环境安装

  • 前提:本地已配置完成 Python 环境
  • 第一种方式 pip install pytest
  • 第二种方式 PyCharm 直接安装

运行第一个脚本

# content of test_sample.py def inc(x):

return x + 1 def test_answer():

assert inc(3) == 5

Pytest 有哪些格式要求?

  • 文件名
  • 方法/函数

Pytest 测试用例编写规则是什么?

类型规则
文件test_开头 或者 _test 结尾
Test 开头
方法/函数test_开头
注意:测试类中不可以添加__init__构造函数

Pycharm 默认测试执行器为Pytest

  1. 进入 Tools->Python Intergrated Tools
  2. 选择 Default test runner 为 pytest

用例结构

  • 三部分构成
    • 用例名称
    • 用例步骤
    • 用例断言

测试用例示例

def test_XXX(self):

# 测试步骤1

# 测试步骤2

# 断言 实际结果 对比 预期结果

assert ActualResult == ExpectedResult

类级别的用例示例

class TestXXX:
    def setup(self):
        # 资源准备
        pass

    def teardown(self):
        # 资源销毁
        pass

    def test_XXX(self):
        # 测试步骤1
        # 测试步骤2
        # 断言  实际结果 对比 预期结果
        assert ActualResult == ExpectedResult

断言(assert),是一种在程序中的一阶逻辑(如:一个结果为真或假的逻辑判断式),目的为了表示与验证软件开发者预期的结果。当程序执行到断言的位置时,对应的断言应该为真。若断言不为真时,程序会中止执行,并给出错误信息。

断言的用法

  • 断言写法
    • assert <表达式>
    • assert <表达式>,<描述>

assert <bool expression>;   

assert <bool expression> : <message>; 

  • 第一种:assert <表达式>
  • 第二种:assert <表达式>,<描述>

def test_a():
    assert True

def test_b():
    a = 1
    b = 1
    c = 2
    assert a + b == c, f"{a}+{b}=={c}, 结果为真"

  • assert <表达式>

def test_c():
    a = 1
    b = 1
    c = 2
    assert 'abc' in "abcd"

import sys
def test_plat():
    assert ('linux' in sys.platform), "该代码只能在 Linux 下执行"

测试装置介绍

类型规则
setup_module/teardown_module全局模块级
setup_class/teardown_class类级,只在类中前后运行一次
setup_function/teardown_function函数级,在类外
setup_method/teardown_method方法级,类中的每个方法执行前后
setup/teardown在类中,运行在调用方法的前后(重点)

参数化

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

参数化应用场景

  • 测试登录场景
    • 测试登录成功,登录失败(账号错误,密码错误)
    • 创建多种账号: 中⽂文账号,英⽂文账号
  • 普通测试用例方法
    • 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

参数化:多参数情况

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

# 数据放在元组中
@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参数,将别名放在列表中

@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 参数(中文)

@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
    
# 创建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")

参数化:笛卡尔积

  • 两组数据
    • 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)

@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}")

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"

pytest 设置跳过、预期失败

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

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

Skip 使用场景

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

xfail 使用场景

  • 与 skip 类似 ,预期结果为 fail ,标记用例为 fail
  • 用法:添加装饰器@pytest.mark.xfail

运行多条用例

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

运行多条用例方式

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

运行结果分析

  • 常用的:fail/error/pass
  • 特殊的结果:warning/deselect(后面会讲)

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

  • --lf(--last-failed) 只重新运行故障。
  • --ff(--failed-first) 先运行故障然后再运行其余的测试

命令行参数 - 常用命令行参数

—help 
-x   用例一旦失败(fail/error),就立刻停止执行
--maxfail=num 用例达到
-m  标记用例
-k  执行包含某个关键字的测试用例
-v 打印详细日志
-s 打印输出日志(一般-vs一块儿使用)
—collect-only(测试平台,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 `

常用的异常处理方法

  • try…except
  • pytest.raises()

异常处理方法 try …except

try:
    可能产生异常的代码块
except [ (Error1, Error2, ... ) [as e] ]:
    处理异常的代码块1
except [ (Error3, Error4, ... ) [as e] ]:
    处理异常的代码块2
except  [Exception]:
    处理其它异常

异常处理方法 pytest.raise()

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

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"

Pytest 结合数据驱动 YAML

数据驱动

  • 什么是数据驱动?

    • 数据驱动就是数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变。简单来说,就是参数化的应用。数据量小的测试用例可以使用代码的参数化来实现数据驱动,数据量大的情况下建议大家使用一种结构化的文件(例如 yaml,json 等)来对数据进行存储,然后在测试用例中读取这些数据。
  • 应用:

    • App、Web、接口自动化测试
    • 测试步骤的数据驱动
    • 测试数据的数据驱动
    • 配置的数据驱动

yaml 文件介绍

  • 对象:键值对的集合,用冒号 “:” 表示
  • 数组:一组按次序排列的值,前加 “-”
  • 纯量:单个的、不可再分的值
    • 字符串
    • 布尔值
    • 整数
    • 浮点数
    • Null
    • 时间
    • 日期

# 编程语言
languages:
  - PHP
  - Java
  - Python
book:
  Python入门: # 书籍名称
    price: 55.5
    author: Lily
    available: True
    repertory: 20
    date: 2018-02-17
  Java入门:
    price: 60
    author: Lily
    available: False
    repertory: Null
    date: 2018-05-11

yaml 文件使用

  • 查看 yaml 文件
    • pycharm
    • txt 记事本
  • 读取 yaml 文件
    • 安装:pip install pyyaml
    • 方法:yaml.safe_load(f)
    • 方法:yaml.safe_dump(f)

import yaml
file_path = './my.yaml'
with open(file_path, 'r', encoding='utf-8') as f:
    data = yaml.safe_load(f)

工程目录结构

  • data 目录:存放 yaml 数据文件
  • func 目录:存放被测函数文件
  • testcase 目录:存放测试用例文件

# 工程目录结构
.
├── data
│   └── data.yaml
├── func
│   ├── __init__.py
│   └── operation.py
└── testcase
    ├── __init__.py
    └── test_add.py

测试准备

  • 被测对象:operation.py
  • 测试用例:test_add.py
  • 测试数据:data.yaml

# operation.py 文件内容
def my_add(x, y):
    result = x + y
    return result
# test_add.py 文件内容
class TestWithYAML:
  @pytest.mark.parametrize('x,y,expected', [[1, 1, 2]])
  def test_add(self, x, y, expected):
    assert my_add(int(x), int(y)) == int(expected)
# data.yaml 文件内容
-
  - 1
  - 1
  - 2
-
  - 3
  - 6
  - 9
-
  - 100
  - 200
  - 300

Pytest 数据驱动结合 yaml 文件

# 读取yaml文件
def get_yaml():
    """
    获取json数据
    :return: 返回数据的结构:[[1, 1, 2], [3, 6, 9], [100, 200, 300]]
    """
    with open('../datas/data.yaml', 'r') as f:
        data = yaml.safe_load(f)
        return data

Pytest 结合数据驱动 Excel

读取 Excel 文件

  • 第三方库

    • xlrd
    • xlwings
    • pandas
  • openpyxl

    • 官方文档: https://openpyxl.readthedocs.io/en/stable/

openpyxl 库的安装

  • 安装:pip install openpyxl
  • 导入:import openpyxl

openpyxl 库的操作

  • 读取工作簿

  • 读取工作表

  • 读取单元格

import openpyxl

# 获取工作簿
book = openpyxl.load_workbook('../data/params.xlsx')

# 读取工作表
sheet = book.active

# 读取单个单元格
cell_a1 = sheet['A1']
cell_a3 = sheet.cell(column=1, row=3)  # A3

# 读取多个连续单元格
cells = sheet["A1":"C3"]

# 获取单元格的值
cell_a1.value

工程目录结构

  • data 目录:存放 excel 数据文件

  • func 目录:存放被测函数文件

  • testcase 目录:存放测试用例文件

# 工程目录结构
.
├── data
│   └── params.excel
├── func

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

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

相关文章

【axios报错异常】: Uncaught ReferenceError: axios is not defined

问题描述: 当前代码在vivo手机和小米手机运行是正常的,点击分享按钮调出相关弹框,发送接口进行分享,但是现在oppo手机出现了问题: 点击分享按钮没有反应. 问题解析: 安卓同事经过查询后,发现打印了错误: 但是不清楚这个问题是安卓端造成的还是前端造成的,大家都不清楚. 问题…

图论练习3

内容&#xff1a;过程中视条件改变边权&#xff0c;利用树状数组区间加处理 卯酉东海道 题目链接 题目大意 个点&#xff0c;条有向边&#xff0c;每条边有颜色和费用总共有种颜色若当前颜色与要走的边颜色相同&#xff0c;则花费为若当前颜色与要走的边颜色不同&#xff0c;…

Java面试——计网篇

一、基础篇 1、 TCP/IP 网络模型 对于同一台设备上的进程间通信&#xff0c;有很多种方式&#xff0c;比如有管道、消息队列、共享内存、信号等方式&#xff0c;而对于不同设备上的进程间通信&#xff0c;就需要网络通信&#xff0c;而设备是多样性的&#xff0c;所以要兼容多…

【Java程序设计】【C00245】基于Springboot的家政服务管理平台(有论文)

基于Springboot的家政服务管理平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的家政服务管理平台 本系统分为前台模块、管理员功能模块、用户功能模块以及服务人员功能模块。 前台模块&#xff1a;系统首页的…

C2-Search-Netlas:一款基于Netlas API的强大C2服务器识别与检测工具

关于C2-Search-Netlas C2-Search-Netlas是一款功能强大的命令与控制&#xff08;C2&#xff09;服务器检测工具&#xff0c;该工具使用Java语言开发&#xff0c;基于Netlas API实现其功能&#xff0c;可以帮助广大研究人员轻松快速地识别和检测目标C2服务器的相关信息。 C2-S…

【目标跟踪】相机运动补偿

文章目录 一、前言二、简介三、改进思路3.1、状态定义3.2、相机运动补偿3.3、iou和ReID融合3.4、改进总结 四、相机运动补偿 一、前言 目前 MOT (Multiple Object Tracking) 最有效的方法仍然是 Tracking-by-detection。今天给大家分享一篇论文 BoT-SORT。论文地址 &#xff0…

XCTF:warmup[WriteUP]

CtrlU查看页面源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible&q…

【Matplotlib】figure方法之图形的保存

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;matplotlib &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…

idea常用设置

1、内存优化 根据自己电脑本身的内存&#xff0c;对idea安装包里bin目录下的idea64.exe.vmoptions文件进行修改 -server -Xms256m -Xmx2048m -XX:MaxPermSize1024m -XX:ReservedCodeCacheSize256m -ea -Dsun.io.useCanonCachesfalse -Djava.Net.preferIPv4Stacktrue -Djsse.e…

STM32--HAL库定时器学习记录(易懂)--持续学习

一、什么是定时器 定时器就是计数器&#xff0c;通过计数完成一系列功能。 二、定时器的分类 定时器分为基本定时器、通用定时器、高级定时器。级别不同&#xff0c;功能不同。级别越高&#xff0c;功能越强。 三、定时器&#xff08;计数器&#xff09;三个重要寄存器 预分…

CSS:水平垂直居中

公共的 CSS 样式&#xff1a; .parent {width: 300px;height: 300px;background-color:#d0e4fe; }.child {width: 100px;height: 100px;background-color:orange; }HTML: <div class"parent"><div class"child"></div> </div>最…

C#之linq和lamda表达式GroupBy分组拼接字符串

文章目录 C#之linq和lamda表达式GroupBy分组拼接字符串业务需求核心代码调试 C#之linq和lamda表达式GroupBy分组拼接字符串 业务需求 点击提示信息&#xff0c;如&#xff1a;“售后单【SH001】序列号【001&#xff0c;002&#xff0c;006】&#xff1b;售后单【SH002】序列号…

华为自动驾驶干不过特斯拉?

文 | AUTO芯球 作者 | 李诞 什么&#xff1f; 华为的智能驾驶方案干不过蔚小理&#xff1f; 特斯拉的智能驾驶[FSD]要甩中国车企几条街&#xff1f; 这华为问界阿维塔刚刚推送“全国都能开”的城区“无图 NCA” 就有黑子来喷了 这是跪久了站不起来了吧 作为玩车14年&…

flask_django_python五金电商网络营销的可视化分析研究

前面部分完成了系统需求分析&#xff0c;了解到新闻数据业务方面的需求&#xff0c;系统主要分为用户管理、五金信息管理、在线留言、系统管理等功能。销的可视化研究&#xff0c;并对这些数据进行处理&#xff0c; 然后对这些数据进行可视化分析和统计。 Python 爬虫技术目前来…

【华为】GRE VPN 实验配置

【华为】GRE VPN 实验配置 前言报文格式 实验需求配置思路配置拓扑GRE配置步骤R1基础配置GRE 配置 ISP_R2基础配置 R3基础配置GRE 配置 PCPC1PC2 抓包检查OSPF建立GRE隧道建立 配置文档 前言 VPN &#xff1a;&#xff08;Virtual Private Network&#xff09;&#xff0c;即“…

Electron实战(二):将Node.js和UI能力(app/BrowserWindow/dialog)等注入html

文章目录 设置webPreferences参数安装electron/remotemain进程中初始化html中使用dialog踩坑参考文档 上一篇&#xff1a;Electron实战(一)&#xff1a;环境搭建/Hello World/打包exe 设置webPreferences参数 为了能够在html/js中访问Node.js提供fs等模块&#xff0c;需要在n…

Django的web框架Django Rest_Framework精讲(二)

文章目录 1.自定义校验功能&#xff08;1&#xff09;validators&#xff08;2&#xff09;局部钩子&#xff1a;单字段校验&#xff08;3&#xff09;全局钩子&#xff1a;多字段校验 2.raise_exception 参数3.context参数4.反序列化校验后保存&#xff0c;新增和更新数据&…

20240131在ubuntu20.04.6下使用whisper不同模式的比对

20240131在ubuntu20.04.6下使用whisper不同模式的比对 2024/1/31 16:07 首先你要有一张NVIDIA的显卡&#xff0c;比如我用的PDD拼多多的二手GTX1080显卡。【并且极其可能是矿卡&#xff01;】 2、请正确安装好NVIDIA最新的驱动程序和CUDA。可选安装&#xff01; 3、配置whisper…

【Linux取经路】进程控制——程序替换

文章目录 一、单进程版程序替换看现象二、程序替换的基本原理三、程序替换接口学习3.1 替换自己写的可执行程序3.2 第三个参数 envp 验证四、结语一、单进程版程序替换看现象 #include <stdio.h> #

深入理解Istio服务网格(一)数据平面Envoy

一、服务网格概述(service mesh) 在传统的微服务架构中&#xff0c;服务间的调用&#xff0c;业务代码需要考虑认证、熔断、服务发现等非业务能力&#xff0c;在某种程度上&#xff0c;表现出了一定的耦合性 服务网格追求高级别的服务流量治理能力&#xff0c;认证、熔断、服…