【测试】Pytest

news2025/1/27 12:44:33

建议关注、收藏!

目录

  • 功能
  • pytest

自动化测试工具。

功能

  1. 单元测试:用于验证代码的最小功能单元(如函数、方法)的正确性。
    简单的语法:不需要继承特定类或使用复杂的结构。断言语句简化。
    自动发现测试:Pytest 会自动查找以 test_ 开头的函数或文件。
def add(a, b):
    return a + b

def test_add():
    assert add(1, 2) == 3

def test_subtract():
    result = 10 - 5
    assert result == 5
pytest #运行
  1. 参数化测试
    @pytest.mark.parametrize 可以在一个测试函数中测试多组输入和输出
@pytest.mark.parametrize("a, b, expected", [
    (1, 2, 3),
    (2, 3, 5),
    (10, 5, 15)
])
def test_add(a, b, expected):
    assert add(a, b) == expected
  1. 功能测试、集成测试、回归测试
  2. 插件
    pytest-django:测试 Django 项目。
    pytest-flask:测试 Flask 应用程序。
    pytest-cov:生成测试覆盖率报告。
    pytest-xdist:支持并行运行测试,提高测试效率。
  3. 测试用例分组和标记
    @pytest.mark给测试用例添加标记,以便运行特定分组的测试。
@pytest.mark.slow
def test_slow_function():
    # 测试代码
    pass
pytest -m slow
  1. 灵活的前置与后置处理(Fixture)
    用于在测试前后进行环境的初始化与清理。
import pytest

@pytest.fixture
def sample_data():
    return {"key": "value"}

def test_with_fixture(sample_data):
    assert sample_data["key"] == "value"
  1. 错误重试与失败处理
    使用插件(如 pytest-rerunfailures)可以重试失败的测试用例。
    生成 HTML 测试报告(使用 pytest-html 插件)。
pytest --html=report.html
  1. 集成 CI/CD
    Pytest 易于与持续集成工具(如 Jenkins、GitLab CI/CD、GitHub Actions)集成,自动化测试流程。

pytest

支持简单单元测试及复杂功能测试
结合requests实现接口测试
结合selenium硒,appium实现自动化功能测试
结合allure继承到jenkins实现持续集成
支持315+种插件
报告、多线程、顺序控制
兼容python的unittest
定制化插件开发

#text.py
def inc(x):
	return x+1
def test_answer():
	assert inc(3)==5

pip install pytest #安装到了base环境
#command里输入
pytest main.py

在这里插入图片描述
命名规则注意:文件名必须得是 test_ 开头 或者 _test 结尾;类要用Test_开头,方法用test_开头,这样行号会出现绿色运行箭头
测试类中不可以添加__init__构造函数,如果添加则不认为是测试类,所有测试方法都识别不到了

pycharm->setting->tools->python intergrated tools->default test runner:pytest

  • 断言:执行到这个位置,对应的断言应为真。当不为真时,程序终止执行并给出错误信息。
def test_x(self):
#测试步骤
#断言 实际结果对比预期结果
	assert ActualResult==ExpectedResult

class Testx:
	def setup(self):
	#资源准备
		pass
	def teardown(self):
	#资源销毁
		pass
	def test_x(self):
	#测试步骤
	#断言 实际结果对比预期结果
		assert ActualResult==ExpectedResult

#断言用法
assert <表达式>
assert <表达式>,<描述>

def test_a():
	assert 'abc' in 'abcd'
import sys
def test_b():
	assert ('linux' in sys.platform),"该代码只能在linux下运行"
  • setup/teardown
    相当于就是某个事件开始前的资源准备->setup;事件完成后的资源销毁->teardown;
    以下是各个层级的setup/teardown:
    在这里插入图片描述
#需要哪个层级的触发 就在哪个地方放哪个

def setup_module():#全局的最多只会执行一次
	print("资源准备:setup module")
#setup teardown不需要成对出现,根据需求选择
def teardown_module():
	print("资源销毁:teardown module")
  • 参数化
    使定量信息变量化。可以对其进行不同的赋值。
    e.g. 对搜索框进行输入测试。这个输入可以设成一个变量,每次只需要调整搜索的输入。
    注意:
  1. 参数化的名字要与方法中的参数名一一对应
  2. 如果传递多个参数,要放在列表中,作为嵌套列表/元组
  3. ids的参数个数要==传递的参数个数
#单参数
import pytest
search_list=['appium','selenium','pytest']
@pytest.mark.parametrize('name',search_list)
def test_search(name):#这个name要和上述的name字段相等,对应上
	assert name in search_list
#多参数
params=[('3+5',8),('2+5',7),('6+5',12)]
@pytest.mark.parametrize("test_input,expected",params,ids=['p1','p2','p3'])
#用例重命名 ids
#ids是对params里面的每个参数进行重命名,可以用这个名字分别代表它们
def test_mark_more(test_input,expected):
	assert eval(test_input)==expected

#笛卡尔积 在测试中叫全量测试 几乎不实际 过于浪费时间
#在排查不确定的问题时可以用
@pytest.mark.parametrize('wd',['appium','selenium','pytest'])
@pytest.mark.parametrize('code',['utf-8','gbk','gb2312'])
def test_dkej(wd,code):
	print(f"wd:{wd},code:{code}")
'''
print(f'.....')
注意:f后面一定要紧跟字符串,不能隔有空格,否则会报错
print语句中加入f就可以起到和format函数类似的作用。
'''
  • 标记测试用例
    只执行需要的一部分测试用例,可以把一个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" #这个是指测试所有标签中不包括ios的用例
pytest -s test_mark_zi_09.py -vs -m apptest #-vs指打印详细日志
pytest -s test_mark_zi_09.py -m "str" #执行标签名为str的所有用例
#-k 可以进行部分匹配 只要标签名里包含这个 就执行
@pytest.mark.int #装饰器 不改变原有代码+增加相关功能 标记新标签"int"
def test_double_int():
	print('test_double_int')
	assert 2==double(1)

#为了防止报出warning,虽然不影响执行
#新建pytest.ini
#这个文件中放入:
[pytest]
markers= str  #多个参数不要写在同一行,要换行且不顶格
		bignum
		float
		int
		zero
		minus
#顶格的换行参数会被认为是key 地位等同于markers

#这样之后 pytest就可以识别出 def[test_double_标签名]这里面的标签名
#e.g. test_double_int 中的'int'/....它们注册成为了标签
  • 跳过及预期失败
    这是pytest的内置标签,可以处理特殊的测试用例
    skip:始终跳过
    skipif:如果…跳过
    xfail:如果…产生一个“期望失败”输出

使用场景:

  1. 调试时不想运行这个用例
  2. 标记无法在某些平台上运行的测试功能
  3. 在某些版本中执行,某些版本则跳过它
    e.g. 当前外部资源不可用时跳过
    如果测试数据是从数据库中取到的;连接数据库的功能,如果返回结果未成功则跳过;开发人员代码未写完;
#解决1:添加装饰器
@pytest.mark.skip 
@pytest.mark.skipif
#解决2:代码中添加跳过代码
pytest.skip(reason='代码未写完')

#1.这些代码直接放在需要跳过的函数def的上一行。
#2.放在函数内部进行条件判断使用
def test_function():
	if not check_login():
		pytest.skip("unsupported configuration")
	print('end')

import pytest
import sys
print(sys.platform)
@pytest.mark.skipif(sys.platform=='darwin',reason='does not run on mac')#mac在这里其实叫darwin
def test_case1():
    print('enter 1')
    assert 1==2

@pytest.mark.skipif(sys.platform=='win',reason='does not run on windows')
def test_case2():
    print('enter 2')
    assert 1==1
 
@pytest.mark.xfail #起到提示的作用,bug改完之后去掉
def test_aaa():
	print("test_xfail1 方法执行")
	assert 2==2 #打印为XPASS
	#assert 2==3 #打印为XFAIL
	
xfail=pytest.mark.xfail

@xfail(reason="bug 404")
def test_sample404():
	assert 0

@pytest.mark.xfail #起到提示的作用,bug改完之后去掉
def test_aaa():
	print("start")
	pytest.xfail(reason="have not done this")#这行之后的函数作用域将不会执行
	print("processing")
  • 运行用例
    运行某个/多个 用例包/用例模块/用例类/用例方法
  1. IDE的界面操作
    多个文件用command选中,右键->run
  2. 代码方式运行【选择这种,不容易出问题】
pytest -v #直接执行当前目录下的所有测试文件
pytest filename.py #test single file
pytest filename.py::ClassName #执行某个类
pytest filename.py::ClassName -v #打印显示具体执行了哪个用例
pytest filename.py::ClassName::test_demo1 -v #执行具体用例
pytest filename.py::test_demo1 -v#执行不属于类的用例

#命令行参数 命令后面加上的...
-help
-x #用例error/fail 则立刻停止执行
'''
冒烟测试:不是全功能的测试,只是大概的测一下,只需要主要核心功能没问题。
'''

--maxfail==num #用例达到多少停止
-m #标记用例 运行这一类的用例

-k #执行包含某个关键字的测试用例
pytest test.py -v -k "str" #运行命名包含"str"的用例
#并告知deselected的个数
pytest test.py -v -k "not str" #运行命名不包含"str"的用例

--collect-only #只收集统计测试用例但不运行 (测试平台,pytest自动导入功能)
--lf #(--last-failed) #只重新运行故障
--ff #(--failed-first)#先运行故障后运行其余的测试
-v #输出更加详细的运行信息
-s #输出调试信息 即print输出的信息
-vs #它俩的组合版

  • 运行结果分析
    常用:fail/error/pass
    特殊:warning/deselect
  1. error:代码写错、某种不正确的断言
  2. fail 样例不通过
  3. warning只是警告,不影响运行
  4. deselect没有被选中的用例
  • 代码执行pytest
    方式一:编写main函数,命令行中使用“python test_name.py ”
if __name__=='__main__':
	#运行当前目录下所有符合规则的用例,包括子目录里的
	pytest.main()
	#运行test_mark1.py::test_dkej模块中某一条用例
	pytest.main(['test_mark1.py::test_dkej','-vs'])
	#运行某个标签
	pytest.main(['test_mark1.py','-vs','-m','dkej'])
# 什么时候这里的__name__!='__main__',当该文件被其他文件导入时

方法二:不使用main,使用python -m pytest test_name.py
(用到jenkins持续集成)

  • 异常处理
    方法1:try…except
try:
	...
except (ValueError,ArithmeticError):
	...
except:
	...

方法2:
获取异常的细节(类型和信息),后面的代码不会继续执行

def test_raise():
	with pytest.raises((ZeroDivisionError,ValueError),match='must be 0 or None'):#如果有match匹配文字的需要,匹配后才能pass
		raise ValueError("value must be 0 or None")
		#raise ZeroDivisionError("除数为0")
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"
  • 数据驱动
    数据改变而驱动自动化测试进行。
    数据量小的测试用例使用代码参数化实现数据驱动。
    数据量大的测试用例使用一种结构化的文件(如yaml,json等)来对数据进行存储,在测试用例中读取这些数据。
    • 应用场景:app,web,接口自动化测试
  • 包含测试步骤的数据驱动、测试数据的数据驱动、配置的数据驱动
import pytest
import yaml #.yml是一种配置文件
class TestDemo:
	@pytest.mark.parametrize("env",yaml.safe_load(open("./env.yml")))
	#parametrize中如果传入的是dict类型,则只读取key
	def test_demo(self,env):
		if "test" in env:
			print("this is test env")
			print(env)
			print(env["test"])#读取到ip 127.0.0.1 
		elif "dev" in env:
			print("this is develop env")

#env.yaml
test:127.0.0.1 #这是字典格式

#env.yaml
- #前面加一杠 转换成列表格式,里面的元素是{'test':'127.0.0.1 '}
test:127.0.0.1 
    • 读取excel文件
      第三方库:xlrd,xlwings,pandas,openpyxl
    • openpyxl
conda install openpyxl
pip install ...

import openpyxl
book=openpyxl.load_workbook('path')#读取工作簿

sheet=book.active#获取当前活跃的工作表

#读取单元格的两种方式
cell_a1=sheet['A1']
cell_a3=sheet.cell(column=1,row=3)

#读取多个连续的单元格
cells=sheet["A1":"C3"] #返回嵌套元组

#获取单元格里的值
cell_a1.value
    • 读取csv文件
      cvs(comma-Separated Values) 以逗号分隔
      以纯文本形式储存
#读取数据
#采用内置函数
def get_csv():
	with open('demo.csv','r')as file:
		raw=csv.reader(file)
		for line in raw:
			print(line)
		
		values=[]
		for row in raw:
			values.append(line)
	return values #传入parametrize
		
    • 读取json文件
      json 是JS对象,javascript object notation
      json结构中对象是{“key”:value};数组是[value1,value2…]

json.loads() or json.load()
json.loads 从 JSON 字符串解析为 Python 对象。
json.load 从文件对象(如 .read() 的结果)解析 JSON 数据,输出字典dict。
data=json.loads(f.read())

#读取json
#内置函数open(),内置库json
#方法 json.loads() , json.dumps()

def get_json():
	with open('demo.json','r')as f:
		data=json.loads(f.read())
#与 json.load(f) 相比,它多了一个中间步骤:
#先读取文件内容f.read()为字符串,再将字符串传递给 json.loads 进行解析。
		print(data) #type:dict
		
		s=json.dumps(data,ensure_ascii=False)#序列化 str->json
		#使得中文字符正常显示
		return list(data.values())
  • 工程目录结构
    在这里插入图片描述
#operation.py
def my_add(x,y):
	res=x+y
	return res

# test_add.py
import openpyxl
import pytest
from mainfolder.func.operation import my_add
def get_excel():
	book=openpyxl.load_workbook('path')#读取工作簿
	sheet=book.active
	values=[]
	for row in sheet:
		line=[]
		for cell in row:
			line.append(cell.value)
		values.append(line)
	return values

class TestWithExcel:
	@pytest.mark.parametrize('x,y,expected',get_excel())
	def test_add(self,x,y,expected):
		assert my_add(int(x),int(y))==int(expected)

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

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

相关文章

Python语法之字典

免责说明&#xff1a;此内容不包含嵌套字典 关注我更新更多初学实例 字典 一.字典的应用场景 思考:数据顺序发生变化&#xff0c;每个数据的下标也会随之变化&#xff0c;如何保证数据顺序变化前后能使用同一的 标准查找数据呢&#xff1f; 答&#xff1a;字典&#xff0c…

mysql客户端命令

目录 结束符 ; \g \G 中断输入 ctrl c 查看命令列表 help ? (\?) connect (\r) status (\s) delimiter (\d) exit (\q) quit (\q) tee (\T) ​编辑 notee (\t) prompt (\R) source (\.) system (\!) ​编辑 use (\u) help contents 结束符 ; \g \G 当我…

更频繁的 Android SDK 发布:更快的创新、更高的质量和更完善

Android 一直致力于让创新更快地进入用户手中。除了每年的平台发布之外&#xff0c;我们还投资了Project Treble、Mainline、Google Play 服务、每月安全更新和季度发布&#xff0c;为 Pixel Drops 提供支持。 未来&#xff0c;Android 将更频繁地发布 SDK&#xff0c;计划于 …

蓝卓总裁谭彰:AI+工业互联网推动制造业数字化转型

近日&#xff0c;新一代工业操作系统supOS6.0在2024中国5G工业互联网大会上重磅发布。 大会期间&#xff0c;工信部新闻宣传中心《人民邮电报》对蓝卓总裁谭彰就“工业互联网人工智能技术融合的思考”“supOS6.0的探索与实践”“未来工业互联网平台的发展方向”展开专题访谈&am…

【WRF-Urban】输入空间分布人为热排放数据的WRF运行全过程总结

目录 数据准备检查新增变量配置(如果有)WPS预处理修改namelist.wpsStep1: geogridStep2: ungribStep3: metgridWRF运行修改namelist.input调试namelist.input运行./real.exe运行./wrf.exe参考WRF模型的基本流程如下: 数据准备 空间分布热排放数据下载及制备可参见另一博客…

如何利用Python爬虫获得1688按关键字搜索商品

在当今的数字化时代&#xff0c;数据已成为企业竞争的核心资源。对于电商行业来说&#xff0c;了解市场动态、分析竞争对手、获取商品信息是至关重要的。Python作为一种强大的编程语言&#xff0c;其丰富的库和框架使得数据爬取变得简单易行。本文将介绍如何使用Python爬虫技术…

Python从0到100(七十三):Python OpenCV-OpenCV实现手势虚拟拖拽

前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能…

【Go】-倒排索引的简单实现

目录 什么是倒排索引 定义 基本结构和原理 分词在倒排索引中的重要性 简单倒排索引的实现 接口定义 简单数据库的实现 倒排索引 正排索引 测试 总结 什么是倒排索引 定义 倒排索引&#xff08;Inverted Index&#xff09;是一种索引数据结构&#xff0c;它是文档检…

php生成图片

前提 开启dg2库 去掉前面的;注释&#xff0c;有的可能会带.dll后缀影响不大 extensiongd2代码 <?php $file imagecreate(100,50); //先生成图片资源$color imagecolorallocate($file,255,255,255); //白色$c imagecolorallocate($file,0,100,255);imagefill($file,0…

MySQL数据库——门诊管理系统数据库数据表

门诊系统数据库his 使用图形化工具或SQL语句在简明门诊管理系统数据库his中创建数据表&#xff0c;数据表结构见表2-3-9&#xff5e;表2-3-15所示。 表2-3-9 department&#xff08;科室信息表&#xff09; 字段名称 数据类型 长度 是否为空 说明 dep_ID int 否 科室…

02、10个富士胶片模拟的设置

二色彩 1、色彩的加减控制全局的饱和度增减&#xff1b; 2、色彩效果只提升暖色系饱和度&#xff1b; 3、FX蓝色大幅度提升蓝色系饱和度&#xff1b; 4、三个参数都不改变颜色的色相。 2.1 色彩 色彩调整的是拍摄画面整体的色彩饱和程度 2.2色彩效果 调整的是画面中暖色…

java全栈day19--Web后端实战(java操作数据库3)

一、MyBatis 1.1介绍 前提引入&#xff1a; controller(控制层)作用&#xff1a;接受请求&#xff0c;响应数据 service(业务层)作用&#xff1a;负责具体的逻辑处理 dao(持久层)作用&#xff1a;数据访问层 一般的访问流程&#xff1a;浏览器发起请求过来&#xff0c;先…

以太网帧、IP数据报图解

注&#xff1a;本文为 “以太网帧、IP数据报”图解相关文章合辑。 未整理去重。 以太网帧、IP数据报的图解格式&#xff08;包含相关例题讲解&#xff09; Rebecca.Yan已于 2023-05-27 14:13:19 修改 一、基础知识 UDP 段、IP 数据包&#xff0c;以太网帧图示 通信过程中&…

Android Vendor Overlay机制

背景介绍&#xff1a; 看Android 15版本更新时&#xff0c;"Android 15 deprecates vendor overlay"。 猜想这个vendor overlay是之前用过的settings overlay&#xff0c; 不过具体是怎么回事呢&#xff1f; 目录 Vendor Overlay介绍 Vendor Overlay工作原理 Ven…

联发科MTK8788_MT8788安卓核心板安兔兔跑分_安卓主板方案商

MT8788安卓核心板具有集成的蓝牙、fm、WLAN和gps模块&#xff0c;是一个高度集成的基带平台&#xff0c;包括调制解调器和应用处理子系统&#xff0c;启用LTE/LTE-A和C2K智能设备应用程序。该芯片集成了工作在2.0GHz的ARM Cortex-A73、最高可达2.0GHz的ARM Cortex-A53和功能强大…

uniapp连接蓝牙操作(蓝牙设备地锁)

介绍&#xff1a; 本文采用uni-app框架来创建一个简单的用户界面&#xff0c;用于搜索、连接和发送命令给蓝牙设备。 1.打开蓝牙适配器 function openBluetooth() {uni.openBluetoothAdapter({success() {uni.offBluetoothDeviceFound();// 监听新设备发现事件uni.onBlueto…

谁说C比C++快?

看到这个问题&#xff0c;我我得说&#xff1a;这事儿没有那么简单。 1. 先把最大的误区打破 "C永远比C快" —— 某位1990年代的程序员 这种说法就像"自行车永远比汽车省油"一样荒谬。我们来看个例子&#xff1a; // C风格 char* str (char*)malloc(100…

宝塔SSL证书申请失败,报错:申请SSL证书错误 module ‘OpenSSL.crypto‘ has no attribute ‘sign‘(已解决)

刚安装宝塔申请SSL就报错&#xff1a;申请SSL证书错误 module OpenSSL.crypto has no attribute sign 面板、插件版本&#xff1a;9.2.0 系统版本&#xff1a;Alibaba Cloud Linux 3.2104 LTS 问题&#xff1a;申请SSL证书错误 module OpenSSL.crypto has no attribute sign…

华为OD-计算正方形数量

华为OD-计算正方形数量 题目解题思路源码实现 题目 解题思路 由于是构成正方形 再结合用例1 很容易直接写出第一行代码 const pointCount await readline();if (pointCount < 4) {console.log(0);return;}然后就是典型的数学题,什么才能构成正方形(这题题主不会,看了解析之…

使用 rvest 包快速抓取网页数据:从入门到精通

介绍 随着大数据和数据科学的迅速发展&#xff0c;互联网数据的抓取已经成为重要的信息获取手段之一。网页抓取&#xff08;Web Scraping&#xff09;可以帮助我们自动化地从网页中提取有价值的数据&#xff0c;应用广泛&#xff0c;包括新闻热点分析、金融数据采集等。在本篇…