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

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

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

相关文章

Jetpack Compose系列(1)-初识Jetpck

Jetpack Compose是什么 2019年的I/O大会上&#xff0c;Google宣布Kotlin成为Android开发首选语言&#xff08;这次不是第一次说了&#xff09;&#xff0c;且后续会有新的Jetpack API和功能将在Kotlin中提供&#xff0c;并同时开源Jetpack Compose。 简介 Jetpack是一套库、…

Camille-学习笔记-web基础知识

web基础1.系统架构 B/S :Browser/Server 网站 界面层&#xff08;UI&#xff09; 业务逻辑层&#xff08;业务&#xff09; 数据访问层&#xff08;数据库&#xff09; 静态网页&#xff1a;和服务器没有数据交互 动态网页&#xff1a;网页数据可以和服务器进行数据交互 URL…

MongoDB从入门到实战之MongoDB简介

前言 相信很多同学对MongoDB这个非关系型数据库都应该挺熟悉的&#xff0c;在一些高性能、动态扩缩容、高可用、海量数据存储、数据价值较低、高扩展的业务场景下MongoDB可能是我们的首选&#xff0c;因为MongoDB通常能让我们以更低的成本解决问题&#xff08;包括学习、开发、…

【面试深度解析】快手后端一面:G1、IOC、AOP、并发、JVM生产问题定位、可重复读、ThreadLocal

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

深度学习-基础过关

众所周知&#xff0c;机器学习是一门跨学科的学科&#xff0c;主要研究计算机如何通过学习人类的行为和思维模式&#xff0c;以实现某些特定的功能或目标。它涉及到概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科&#xff0c;使用计算机作为工具并致力于真实实时的…

IDEA JDBC配置

一、在pom中添加依赖 <dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency></dependencies> 然后同步一下 二、编写代码…

前端入门第三天

目录 一、CSS定义 二、CSS引入方式 三、基础选择器 1.标签选择器 2.类选择器 3.id选择器 4.通配符选择器 5.画盒子 四、文字控制属性 1.字体大小 2.字体粗细 3.字体倾斜 4.行高 1.行高-垂直居中 5.字体族 6.font复合属性 7.文本缩进 8.文本对齐方式 1.水平对…

Java Swing实现思聪吃热狗游戏

引言 Java Swing&#xff0c;一种灵活的图形用户界面库&#xff0c;让我们可以以相对简便的方式创建图形化应用程序。在本文中&#xff0c;我们将讲述如何借助Swing构建一个简单的游戏&#xff1a;DogGame&#xff0c;它的规则是控制一只名为Wsc的狗来捕捉飞来的热狗。让我们浏…

PHP中的stdClass:一个动态的空白板

PHP中的stdClass&#xff1a;一个动态的空白板 在PHP编程中&#xff0c;灵活性和动态性是开发人员追求的重要目标。而stdClass作为PHP中的一个特殊类&#xff0c;为我们提供了一个通用的空白板&#xff0c;允许在运行时动态地添加属性和方法。它的存在为处理动态数据结构和临时…

使用gcc/g++查看C语言预处理,编译,汇编,连接,以及动静态库的区分

文章目录 使用gcc/ggcc如何完成编译后生成可执行文件&#xff1f;预处理(进行宏替换)编译&#xff08;生成汇编&#xff09;汇编&#xff08;生成机器可识别代码&#xff09;连接&#xff08;生成可执行文件或库文件&#xff09;最后记忆小技巧 在这里涉及到一个重要的概念&…

《HTML 简易速速上手小册》第4章:HTML 的表单与输入(2024 最新版)

文章目录 4.1 表单的基础&#xff08;&#x1f4dd;&#x1f680;&#x1f4ac; 开启沟通的大门&#xff09;4.1.1 表单基础知识点4.1.2 基础示例&#xff1a;创建一个简单的注册表单4.1.3 案例扩展一&#xff1a;创建一个调查问卷4.1.4 案例扩展二&#xff1a;创建一个预订表单…

Gson源码解读

一&#xff0c;概述 gson作为流行的json工具&#xff0c;笔者使用较多。本文主要目的是解读下Gson的源码实现&#xff0c;就没有然后了。 二&#xff0c;实例 实例如下图所示&#xff0c;笔者简单调用gson的toJson方法获得json字符串&#xff0c;fromJson则从json字符串解析…

最新2024如何解决谷歌浏览器Chrome谷歌翻译无法使用问题

快速恢复谷歌浏览器一键翻译功能在Chrome 中安装好【翻译】插件 Macbook 操作步骤&#xff1a; 1点击“前往”&#xff0c;打开“前往文件夹” 2 在对话框中输入“/etc” 囝找到“hosts”文件&#xff0c;复制粘贴到桌面 3 在复制的文件最后新起一行&#xff0c;输入并保存&am…

【CSS + ElementUI】el-tree下拉扩展图标置于右侧

效果图 代码实现 <template><div class"search_resource"><el-tree class"filter-tree" ref"tree" default-expand-all :data"directoryList" :props"defaultProps"icon-class"el-icon-arrow-right…

飞凌嵌入式RK3568开发板蓝牙收、发文件测试

本文由电子发烧友论坛用户fsdzdzy提供&#xff0c;感谢分享。飞凌嵌入式每月定期开展新的开发板体验活动&#xff0c;欢迎更多工程师朋友的关注和参与。 飞凌嵌入式OK3568-C开发板板载WiFi&BT模组&#xff0c;蓝牙版本为Bluetooth 5.0&#xff0c;速率高达3Mbps。笔者将在本…

MySQL之谈谈MySQL里的日志

文章目录 前言一、SQL是如何做更新操作的二、MySQL中的redo log三、MySQL中的binlog四、聊聊两阶段提交总结 前言 上一章我们讲了一条SQL是如何做查询的&#xff0c;其中经历了许多步骤。这次来讲讲一条SQL是如何做更新操作的。 常有大佬说他可以把MySQL恢复到半个月内任意一秒…

2024年美赛B题:寻找潜水器 Searching for Submersibles 思路模型代码解析

2024年美赛B题&#xff1a;寻找潜水器 Searching for Submersibles 思路模型代码解析 【点击最下方群名片&#xff0c;加入群聊&#xff0c;获取更多思路与代码哦~】 问题翻译 海上游轮迷你潜艇&#xff08;MCMS&#xff09;是一家位于希腊的公司&#xff0c;专门制造能够将人…

jQuery前段开发--星级评价和图形跟随指针移动

一、实验原理&#xff1a; 当鼠标移入某个星星&#xff0c;前面的星星都会被点亮&#xff1b;当鼠标移出&#xff0c;星星将会变暗&#xff0c;单击某个星星后&#xff0c;即可完成评论&#xff0c;此时鼠标移出后&#xff0c;被单击星星前面的星星都会被点亮&#xff0c;后面…

GmSSL - GmSSL的编译、安装和命令行基本指令

文章目录 Pre下载源代码(zip)编译与安装SM4加密解密SM3摘要SM2签名及验签SM2加密及解密生成SM2根证书rootcakey.pem及CA证书cakey.pem使用CA证书签发签名证书和加密证书将签名证书和ca证书合并为服务端证书certs.pem&#xff0c;并验证查看证书内容&#xff1a; Pre Java - 一…

在Mixamo网站上,下载的模型导入unity后没有材质怎么解决

在Mixamo网站上&#xff0c;下载的模型导入unity后没有材质 1.导入的模型没有材质2.解决方法3.提取后就有材质了 1.导入的模型没有材质 2.解决方法 选中导入的模型 > 选择提取纹理>选择你要提取到的文件夹(默认是当前文件夹)>点击 fix now 3.提取后就有材质了