Python 中 openpyxl 模块封装,读写 Excel 文件中自动化测试用例数据

news/2024/4/23 16:27:52/文章来源:https://blog.csdn.net/weixin_56331124/article/details/129248583

只有测试数据和错误提示信息不同,其他代码都是一样的,不这样不易修改数据和维护,会有两点痛点

1.代码冗余极其严重, 程序可读性不佳

2.程序拓展性很差

往往我们在自动化测试汇总,会将数据放在 Excel 文件、CSV文件、数据库

Python 中处理 excel 数据的模块非常多,比如: xlxd(只读)、xlwd(只写)、openpyxl(可读写)

我们会 采用数据驱动思想,使用 openpyxl 当中的 load_workbook 来处理已存在的 Excel 文件数据,只能读写已 .xlsx 为拓展名的文件;openpyxl 当中的 workbook 方法,用于新建 excel, 几乎不用

以 .xlsx 为拓展名的文件,为一个 Excel 文件对象,一个 excel 对象中, 往往会有多个表单,一个表单中,有多个单元格对象;

重点:

  • 从 excel 文件中获取的 整数 为 int 类型、获取的 小数 为 float 类型
  • 除了 数字类型(小数、整数、浮点数)为 int、float 类型 以外, 其他所有有写内容的位置,获取的数据全部为 字符串 类型
  • 如果是 空 的单元格不写任何内容,读取的是 空 类型
  • 在单元各种写入 FALSE 显示为大写,格式为 bool,跟单元格的格式有关系

问:对 excel 相关操作使用类来封装? 封装有什么好处呢?

痛点:

  • 每个接口每次都要打开文件,定位表单,获取数据,如果有100个那么每个都需要这几步

封装好处:

  • 利于扩展、更简洁、可读性好,让程序的拓展性更好,让代码更加简洁,复用性高
  • 封装后只要导入封装好的类,然后指定 Excel 文件名 和 表单名,就能够获取到所有的测试用例就两行代码

1、以字典(键值对的形式)数据类型,发起请求;
2、在 Excel 中写 字典 还是 json 好?

  • 从 Excel 中读取出来就是字符串,不管是传给data、params,还是 json 也好,都是用 json 格式的参数,写在 Excel 中最方便;
  • json 参数一目了然;取出来是字符串,方便转换;

一、基本的使用

Excel 文件和下面的py文件代码一定要在同一个文件夹内,不然需要指定具体的 Excel 文件路径-------大家都是大佬我就不多说了

读取数据不需要关闭文件,写入必须关闭文件;

from openpyxl import load_workbook# 第一步. 打开 excel 文件:使用load_workbook(译:楼的我的不可)传入文件名
wb = load_workbook("cases.xlsx")    # 返回创建一个Workbook的对象, 相当是一个excel文件# 获取所有的表单名# print(wb.sheetnames)   # 第二步. 定位表单两种方式   
# active(译:艾克体舞)是默认第一个表单
# ws = wb.active  # 默认获取第一个激活的表单, 会创建一个Worksheet对象, 相当于一个表单# 也可以指定表单【'表单名'】
ws = wb['multiply']# 第三步. 定位单元格 cell(译:赛欧),row:(译:肉)行、column:(译:犒劳木)列
one_cell = ws.cell(row=2, column=2)     # 会创建一个Cell对象, 相当于一个单元格# 使用 Cell(译:赛欧)对象中的 value 属性, 能获取单元格中的值
# print(one_cell.value)      # 也可以   a = ws.cell(2, 2).value      print(a)# 方法一: 定位单元格后,使用value属性,将数据写入到指定的单元格
one_cell.value = "休想"   # 修改单元格的值# 方法二: 定位表单,使用cell方法,将数据写入到指定的单元格
ws.cell(row=2, column=3, value="休想")# 保存 excel 文件     save(译:赛乌)
# 写入如果报错:PermissionError: [Errno 13] Permission denied: 'cases.xlsx' ,一定是excel文件未关闭
wb.save("cases.xlsx")

Excel 文件及打印结果:


二、获取下面表单中数据

方法一:cell 方法:

—不推荐使用,因为只能获取固定的行到行、列到列之间的数据

from openpyxl import load_workbook  # 对已经存在的excel进行读写操作# 1. 打开excel文件
wb = load_workbook("cases.xlsx")    # 会创建一个Workbook的对象, 是一个excel文件# 2. 定位表单
ws = wb['aaa']# 3. 定位单元格
# 方法一:获取表单中数据:使用ws(译:我可谁特)当中的cell(译:赛欧)方法
# range(译:软解)
# min_row(译:敏.绕)代表最小行号:max_row(译:马克思.肉):最大行号
# min_column(译:敏.犒劳木)最小列号、max_column(译:敏.犒劳木):最大列号for row in range(ws.min_row+1, ws.max_row+1):           # 获取行号,range中最后一位取不到,需要+1for col in range(ws.min_column, ws.max_column+1):   # 获取列号data = ws.cell(row, col).value                  # 获取值,使用value属性print("值为: {}\n类型为: {}".format(data, type(data)))   # 打印结果

代码执行结果文档第一行:


方法二:使用 load_workbook 中 iter_rows(译:艾特.肉死)方法 + zip 函数 获取表单中数据
  -----推荐使用这用,在自动化测试过程中每执行一条测试用例,都可以使用表头来获取具体的值

from openpyxl import load_workbook  # 对已经存在的excel进行读写操作# 1. 打开excel文件
wb = load_workbook("cases.xlsx")    # 会创建一个Workbook的对象, 是一个excel文件# 2. 定位表单
ws = wb['aaa']# min_row(译:敏.绕)代表最小行号:max_row(译:马克思.肉):最大行号
# min_column(译:敏.犒劳木)最小列号、max_column(译:敏.犒劳木):最大列号# 3. 定位单元格
# 方法二:使用 load_workbook 中 iter_rows(译:艾特.肉死)方法获取表单中数据
# openpyxl 版本为2.6以上,要不没有参数:values_only
# 获取的是单元格位置 使用 values_only = False 属性默认获取单元格对象
# 获取的是单元格位置 使用 values_only = True 后获取的是单元格的值# 获取表头元祖,表头位置为0,表头为第一行,最小行号可以不写1,因为最大行号是1
# 结果为生成器对象,需要使用 tuple 转换为元祖,转换后为嵌套元祖的元祖,使用 位置 0 来获取表头第一个元素
head_data_tuple = tuple(ws.iter_rows(min_row=1, max_row=1, values_only=True))[0]
print(head_data_tuple)# 获取除表头外测试用例数据,和获取表头一样,最大行,最小列可以不写
for one_tuple in tuple(ws.iter_rows(min_row=2, max_row=5, min_col=1, max_col=7, values_only=True)):print(one_tuple)# 表头和测试数据结果
# ('case_id', 'title', 'l_data', 'r_data', 'expected', 'actual', 'result')
# (1, '负数与负数相乘', -2, -4, 8, None, None)
# (2, '负数与正数相乘', -3, 4, 12, None, None)
# (3, '零与零相乘', 0, 0, 0, None, None)
# (4, '正数与正数相乘', 5, 3, -15, None, None)head_data_tuple1 = tuple(ws.iter_rows(min_row=1, max_row=1, values_only=True))[0]
one_list1 = []
for one_tuple1 in tuple(ws.iter_rows(min_row=2, max_row=5, min_col=1, max_col=7, values_only=True)):# 表头的元祖和数据元祖,使用 zip 方法进行转换(返回zip的生成器对象)# 在使用 dict(译:迪克特)转换成字典# 使用 append(译:额喷的)添加到列表当中,获取到一个嵌套字典的列表one_list1.append(dict(zip(head_data_tuple1, one_tuple1)))
print(one_list1)     # 打印结果# 结果:
# [{'case_id': 1, 'title': '负数与负数相乘', 'l_data': -2, 'r_data': -4, 'expected': 8, 'actual': None, 'result': None}, 
#  {'case_id': 2, 'title': '负数与正数相乘', 'l_data': -3, 'r_data': 4, 'expected': 12, 'actual': None, 'result': None}, 
#  {'case_id': 3, 'title': '零与零相乘', 'l_data': 0, 'r_data': 0, 'expected': 0, 'actual': None, 'result': None}, 
#  {'case_id': 4, 'title': '正数与正数相乘', 'l_data': 5, 'r_data': 3, 'expected': -15, 'actual': None, 'result': None}]

三、openpyxl 模块的封装:

使用 ddt 进行数据驱动,会将嵌套字典的列表进行拆包为不同的字典,每一个字典就是一条用例数据,取出预期结果和实际结果,msg;
那么以后就可以写一个实例方法就可以测试多条用例,因为每一个实例方法之间只有数据不同其他的代码都相同;

from openpyxl import load_workbookclass HandleExcel:"""封装excel文件处理类"""def __init__(self, filename, sheetname=None):"""      定义构造方法:param filename: 文件名=实例属性:param sheetname: 表单名,如果表单名只有一个可以设置为默认值"""self.filename = filenameself.sheetname = sheetnamedef get_cases(self):"""获取所有的测试用例,实例方法:return:为嵌套字典的列表"""# 打开文件:使用load_workbook(楼的我的不可)传入文件名wb = load_workbook(self.filename)   # 返回创建一个Workbook的对象, 相当是一个excel文件if self.sheetname is None:          # 定位表单,判断是否制定表单默认空,为第一个表单ws = wb.active                  # active 获取第一个表单else:ws = wb[self.sheetname]         # 否则获取指定的表单# min_row = 最小行号,max_row=最大行号(可以不写)# min_col = 最小列号,max_col=最大列号# values_only = 获取单元格的值# 获取表头的信息,使用 iter_rows(艾特木肉丝)方法,嵌套元祖的元祖,省略最小行号head_data_tuple = tuple(ws.iter_rows(max_row=1, values_only=True))[0]one_list = []for one_tuple in tuple(ws.iter_rows(min_row=2, values_only=True)):  # 不需要表头最小行号为2,不需要最大行号,最大最小列号# zip 函数将表头的元祖与每一行用例所在的元祖进行拼接,dict(译:迪克特) 转换为字典后,添加到列表当中 one_list = []one_list.append(dict(zip(head_data_tuple, one_tuple)))return one_list    # 为嵌套字典的列表def get_one_case(self, row):"""获取某一条测试用例:param row: 行号:return:嵌套字典的列表,使用位置进行获取"""return self.get_cases()[row - 1]def write_result(self, row, actual, result):"""(维泽。瑞走特)写入数据到测试用例指定的行列中:param row: 行号:param actual: 实际结果:param result: 用例执行的结果(Pass或者Fail):return:"""# 同一个Workbook对象, 如果将数据写入到多个表单中, 那么只有最后一个表单能写入成功,需要创建不同的对象other_wb = load_workbook(self.filename)     # 创建对象 = 打开一个文件if self.sheetname is None:other_ws = other_wb.activeelse:other_ws = other_wb[self.sheetname]# 写入if isinstance(row, int) and (2 <= row <= other_ws.max_row):     # 不能修改表头,下一行开始,行号大于2,小于最大的行号other_ws.cell(row=row, column=6, value=actual)              # 在第六行写入实际结果other_ws.cell(row=row, column=7, value=result)              # 在第七行写入用例执行的结果other_wb.save(self.filename)                                # save 保存文件other_wb.close()        # close(译:科楼司)关闭 ----- 读数据的时候不需要关闭,写数据的时候可关闭或不关闭else:   # 如果不是整数,行号小于2,并且大于最大的行号print("传入的行号有误, 行号应为大于1的整数")if __name__ == '__main__':      # 自己写的模块自己用使用 main 函数filename = "cases.xlsx"sheetname = "Sheet1"     # 指定第二个表单名# 创建一个对象,filename=文件名和sheetname=表单名可以不传# do_excel = HandleExcel(filename)  # 传文件名,不传默认第一个表单do_excel = HandleExcel(filename, sheetname)# 获取所有的测试用例cases,使用对象调用实例方法cases = do_excel.get_cases()print(cases)# 写入在第二行写入"初心", "青柠"a = do_excel.write_result(2, "初心7", "青柠")print(a)

最后:下方这份完整的自动化测试视频学习教程已经整理上传完成,朋友们如果需要可以自行免费领取 【保证100%免费】

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

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

相关文章

Python-scatter散点图及颜色大全

# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as pltplt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus] False #matplotlib画图中中文显示会有问题&#xff0c;需要这两行设置默认字体plt.xlabel(X) plt.ylabel(Y) plt.xlim…

【IP技术】ipv4和ipv6是什么?

IPv4和IPv6是两种互联网协议&#xff0c;用于在互联网上标识和寻址设备。IPv4&#xff08;Internet Protocol version 4&#xff09;是互联网协议的第四个版本&#xff0c;是当前广泛使用的互联网协议。IPv4地址由32位二进制数构成&#xff0c;通常表示为4个十进制数&#xff0…

大数据技术之Hive(四)分区表和分桶表、文件格式和压缩

一、分区表和分桶表1.1 分区表partitionhive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录&#xff0c;每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择式选择查询所需要的分区&#xff0c;这样的查询效率辉提高很多。1.1.1 分区表基本语…

2023年蜂巢科技最新面试题

2023年蜂巢科技最新面试题 bio与nio的区别 bio同步阻塞io&#xff1a;在此种⽅式下&#xff0c;⽤户进程在发起⼀个IO操作以后&#xff0c;必须等待IO操作的完成&#xff0c;只有当真正完成了IO操作以后&#xff0c;⽤户进程才能运⾏。JAVA传统的IO模型属于此种⽅式&#xff0…

flink常用算子介绍

flink任务中【Transformation 数据转换】是对数据进行操作&#xff0c;有 Map、FlatMap、Filter、KeyBy 、Reduce 、Fold 、Aggregations、Window 、WindowAll 、Union 、Window join 、Split 、Select 、Project 等&#xff0c;通过对数据的操作&#xff0c;转换成想要的数据&…

HttpRunnerManager部署

基于HttpRunner的接口自动化测试平台: HttpRunner, djcelery and Django_. HttpRunner手册: http://cn.httprunner.org/git地址&#xff1a;httprunner/HttpRunnerManager: 基于 HttpRunner 的 Web 测试平台&#xff0c;已停止维护。 (github.com)部署机器&#xff1a;linux部署…

vue3+rust个人博客建站日记4-Vditor搞定MarkDown

即然是个人博客&#xff0c;那么绝对不能丢给自己一个大大的输入框敷衍了事。如果真是这样&#xff0c;现在就可以宣布项目到此结束了。如今没人享受用输入框写博客。作为一个有追求的程序员&#xff0c;作品就要紧跟潮流。 后来&#xff0c;Markdown 的崛起逐步改变了大家的排…

华为OD机试题,用 Java 解【火星文计算 2】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…

跑步戴哪种蓝牙耳机比较好,五款适合跑步的蓝牙耳机推荐

跑步当中佩戴的蓝牙耳机&#xff0c;佩戴舒适度以及牢固度是我们首要关注的&#xff0c;耳机的材质还有耳机的防水能力&#xff0c;都是十分需要注意的方面。那具体在挑选运动耳机当中需要如何选择呢&#xff1f;下面收集的一些在运动当中比较好用的运动蓝牙耳机分享给大家。1、…

华为OD机试题,用 Java 解【机器人走迷宫】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…

力扣每日一题(2023年2月)

2023年2月期每日一题第一天 &#xff08;2325. 解密消息&#xff09;第十六天&#xff08;2341. 数组能形成多少数对&#xff09;第十七天 &#xff08;1139. 最大的以 1 为边界的正方形&#xff09;第十八天 &#xff08;1237. 找出给定方程的正整数解&#xff09;第十九天 &a…

【再临数据结构】Day1. 稀疏数组

前言 这不单单是稀疏数组的开始&#xff0c;也是我重学数据结构的开始。因此&#xff0c;在开始说稀疏数组的具体内容之前&#xff0c;我想先说一下作为一个有着十余年“学龄”的学生&#xff0c;所一直沿用的一个学习方法&#xff1a;3W法。我认为&#xff0c;只有掌握了正确的…

Apache Hive入门

文章目录一、Apache Hive概述1.1、什么是Hive1.2、使用Hive原因1.3、Hive和Hadoop关系二、Hive功能思想2.1、映射信息记录2.2、SQL语法解析、编译三、Hive架构、组件3.1、Hive架构图3.2Hive组件四、Hive常用操作4.1、数据类型4.1.1、基本数据类型4.1.2、集合数据类型4.2、数据库…

本地新项目上传到git的详细步骤

前提&#xff1a;你本地的项目目录里要记得添加.gitignore忽略文件&#xff0c;免得把一些无用的文件提交&#xff0c;内容如下&#xff0c;可直接粘贴&#xff1a; # Created by .ignore support plugin (hsz.mobi) ### Java template # Compiled class file *.class# Log fi…

2023-02-28 mmap的原理及使用-思考

摘要: 最近在使用mmap解决数据库内存占用损耗过高导致OOM的问题, 不得不说在有些场景下mmap是非常有用. 本文主要涉及一些对mmap的思考. mmap本身的思考: mmap和文件系统的交互规则是什么mmap中给进程虚拟内存映射的文件上的部分,是什么? 为什么是页缓存? 有没有文件缓存?…

华为OD机试题,用 Java 解【连续字母长度】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…

百度CTO王海峰:深度学习平台+大模型,夯实产业智能化基座

2月27日&#xff0c;中国人工智能学会首届智能融合产业论坛在成都顺利举办。本届论坛由中国人工智能学会&#xff08;CAAI&#xff09;主办&#xff0c;中国人工智能学会智能融合专委会、百度公司、深度学习技术及应用国家工程研究中心和电子科技大学联合承办。中国工程院多名院…

企业级React Hooks实战开发指南

背景 大家有没有发现一个问题&#xff0c;我们从任何招聘网站上看到关于React(现在90%都是React Hooks)开发的招聘岗位薪资一定都比其他前端岗位的高&#xff0c;那是什么原因呢&#xff1f;本质的原因是&#xff1a;React学习成本高&#xff0c;导致学习的人少&#xff0c;然…

跟对象介绍十个常用的 Python 内置函数,她夸了我一整天

内置函数是什么 了解内置函数之前&#xff0c;先来了解一下什么是函数 将使用频繁的代码段进行封装&#xff0c;并给它起一个名字&#xff0c;当我们使用的时候只需要知道名字就行 函数就是一段封装好的、可以重复使用的代码&#xff0c;函数使得我们的程序更加简洁、模块化&a…

Goframe快速创建项目,并使用Cli工具创建dao、service、logic

GoFrame项目创建与Cli工具创建1.项目创建2.Mysql数据库配置3.Cli工具dao自动生成4.业务模型须知5.Cli工具service/logic自动生成 - 接口6.Controller/Api创建1.项目创建 官网 - 项目创建-init 开发文档 - 目录介绍 官网 - 示例项目 1.gf init 项目名 &#xff08;创建项目…