测试学习记录,仅供参考!
数据驱动
结合 pytest 框架参数化处理对测试用例做参数化;介绍 Json 格式文件、yaml 格式文件、Excel 格式文件 三种文件方式去做测试用例参数化;
三、使用Excel文件对测试用例做参数化
简介
在日常工作中,经常需要处理Excel 数据,例如读取、写入、修改、分析等等。
使用Excel文件存放测试用例,可以使得测试数据更加直观和易于管理。
Python 是一种强大的编程语言,可以通过其丰富的第三方库来操作 Excel。但是,直接使用原生库进行操作可能会比较繁琐,不够简洁高效。因此,可以封装一个工具类,来简化Excel的操作过程,提高开发、测试效率。
使用 openpyxl 模块处理 Excel 数据(若选择其他第三方库,其他模块自行学习了解);
示例:封装读取 Excel 文件方法
处理列数据
9、有些输入数据只需要一列,这种情况下只需要读取这一列的数据即可;
再写一个方法处理列数据,可参照处理行数据信息;
from openpyxl import load_workbook
from openpyxl.utils.exceptions import InvalidFileException
from util_tools.logs_util.recordlog import logs
import os
class ExcelDataReader:
def __init__(self, file_path):
self.file_path = file_path
abspath = os.path.abspath(self.file_path)
if not os.path.isfile(abspath):
raise FileNotFoundError(f'文件路径不存在:{abspath}')
self.workbook = load_workbook(self.file_path, read_only=False)
def read_entire_column(self, sheet_name='Sheet1', column_index=1):
"""
获取Excel文件一整列的数据
:param sheet_name: sheet页名称
:param column_index: 要返回哪一列的数据,索引从1开始
:return:
"""
sheet = self.workbook[sheet_name]
for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
# 迭代器对象--获取的结果是单元格名称,例如:A1、A2、A3...)
print(row)
def close(self):
self.workbook.close()
if __name__ == '__main__':
exl = ExcelDataReader('../../data/login_test.xlsx')
print(exl.read_entire_column())
9-1、 从运行结果可以查看到是一个元组类型;
(<Cell 'Sheet1'.A1>,)
(<Cell 'Sheet1'.A2>,)
(<Cell 'Sheet1'.A3>,)
(<Cell 'Sheet1'.A4>,)
(<Cell 'Sheet1'.A5>,)
None
进程已结束,退出代码为 0
9-2、需要再循环这个迭代器对象,然后用循环的值去获取单元格的数据
from openpyxl import load_workbook
from openpyxl.utils.exceptions import InvalidFileException
from util_tools.logs_util.recordlog import logs
import os
class ExcelDataReader:
def __init__(self, file_path):
self.file_path = file_path
abspath = os.path.abspath(self.file_path)
if not os.path.isfile(abspath):
raise FileNotFoundError(f'文件路径不存在:{abspath}')
self.workbook = load_workbook(self.file_path, read_only=False)
def read_entire_column(self, sheet_name='Sheet1', column_index=1):
"""
获取Excel文件一整列的数据
:param sheet_name: sheet页名称
:param column_index: 要返回哪一列的数据,索引从1开始
:return:
"""
sheet = self.workbook[sheet_name]
for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
# 循环迭代器对象,然后用循环的值去获取单元格的数据
print(row[0].value)
def close(self):
self.workbook.close()
if __name__ == '__main__':
exl = ExcelDataReader('../../data/login_test.xlsx')
print(exl.read_entire_column())
9-3、 成功获取到第一列每一行的数据内容;
username
admin123
admin111
admin123
admin
None
进程已结束,退出代码为 0
9-4、 定义一个列表把每一行数据存储起来;
from openpyxl import load_workbook
from openpyxl.utils.exceptions import InvalidFileException
from util_tools.logs_util.recordlog import logs
import os
class ExcelDataReader:
def __init__(self, file_path):
self.file_path = file_path
abspath = os.path.abspath(self.file_path)
if not os.path.isfile(abspath):
raise FileNotFoundError(f'文件路径不存在:{abspath}')
self.workbook = load_workbook(self.file_path, read_only=False)
def read_entire_column(self, sheet_name='Sheet1', column_index=1):
"""
获取Excel文件一整列的数据
:param sheet_name: sheet页名称
:param column_index: 要返回哪一列的数据,索引从1开始
:return:
"""
column_data = []
sheet = self.workbook[sheet_name]
for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
column_data.append(row[0].value)
return column_data
def close(self):
self.workbook.close()
if __name__ == '__main__':
exl = ExcelDataReader('../../data/login_test.xlsx')
print(exl.read_entire_column())
9-5、 运行查看结果,已经能够成功获取到第一列的数据;
['username', 'admin123', 'admin111', 'admin123', 'admin']
进程已结束,退出代码为 0
9-6、获取指定列数据(例如第二列)
if __name__ == '__main__':
exl = ExcelDataReader('../../data/login_test.xlsx')
# 获取第二列的数据
print(exl.read_entire_column(column_index=2))
运行结果:
['password', 123456, 123456, 111111, None]
进程已结束,退出代码为 0
9-7、添加 异常处理、日志、关闭文件 释放内容空间资源操作;
# 引进 openpyxl 模块 load_workbook 方法
from openpyxl import load_workbook
# 引入 openpyxl 的一个异常处理
from openpyxl.utils.exceptions import InvalidFileException
# 引入日志
from util_tools.logs_util.recordlog import logs
# 引入os模块
import os
# 创建一个类
class ExcelDataReader:
"""
读取Excel文件数据
"""
# 写一个初始化构造方法
def __init__(self, file_path):
# 定义实例属性
self.file_path = file_path
# 写一下相对路径并返回出去
abspath = os.path.abspath(self.file_path)
# if判断 传进来的文件路径不存在(没有找到)时
if not os.path.isfile(abspath):
# 抛出异常提示
raise FileNotFoundError(f'文件路径不存在:{abspath}')
# read_only:控制工作簿是否以只读模式打开,若为True,工作簿以只读模式打开,不允许对工作簿进行修改
self.workbook = load_workbook(self.file_path, read_only=False)
def read_entire_row(self, sheet_name='Sheet1', row_index=1):
"""
获取Excel文件一整行的数据
:param sheet_name: sheet页名称
:param row_index: 要返回哪一行的数据,索引从1开始
:return:
"""
# 调用上面初始化的打开这个文件的对象 self.workbook 列表里面是获取哪一行它的名称
sheet = self.workbook[sheet_name]
# 列表推导式
rows_data = [cell.value for cell in sheet[row_index]]
return rows_data
def read_multiple_rows(self, sheet_name='Sheet1'):
"""
读取Excel多行的数据,每一行数据组成一个列表
:param sheet_name: sheet页名称
:return: 返回list,例如:[['admin123','123456'],[],[],...]
"""
try:
# 在最外层定义一个空列表
all_rows_data = []
# 第一步跟上面一样,先拿到sheet这个对象
sheet = self.workbook[sheet_name]
# 调用 max_column 方法获取到最大的列数(行数 .max_row)
max_col = sheet.max_column
for row in sheet.iter_rows(min_row=1, max_row=sheet.max_row, min_col=1, max_col=max_col):
# row 是一个迭代器对象--但是不是需要获取的结果
# print(row)
# 列表推导式
row_data = [cell.value for cell in row]
# 调用append方法追加每一行的数据
all_rows_data.append(row_data)
return all_rows_data
except Exception as e:
logs.error(f'读取所有行数据异常,原因为:{e}')
finally:
self.close()
def read_entire_column(self, sheet_name='Sheet1', column_index=1):
"""
获取Excel文件一整列的数据
:param sheet_name: sheet页名称
:param column_index: 要返回哪一列的数据,索引从1开始
:return:
"""
column_data = []
try:
sheet = self.workbook[sheet_name]
for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
column_data.append(row[0].value)
return column_data
except Exception as e:
logs.error(f'读取整列数据异常,原因为:{e}')
finally:
self.close()
def close(self):
self.workbook.close()
# 调试查看
if __name__ == '__main__':
# 实例化类--里面是文件路径
exl = ExcelDataReader('../../data/login_test.xlsx')
print(exl.read_entire_column(column_index=2))
获取某一个单元格的数据
10、读取某一个单元格的数据;
# 引进 openpyxl 模块 load_workbook 方法
from openpyxl import load_workbook
# 引入 openpyxl 的一个异常处理
from openpyxl.utils.exceptions import InvalidFileException
# 引入日志
from util_tools.logs_util.recordlog import logs
# 引入os模块
import os
# 创建一个类
class ExcelDataReader:
"""
读取Excel文件数据
"""
# 写一个初始化构造方法
def __init__(self, file_path):
# 定义实例属性
self.file_path = file_path
# 写一下相对路径并返回出去
abspath = os.path.abspath(self.file_path)
# if判断 传进来的文件路径不存在(没有找到)时
if not os.path.isfile(abspath):
# 抛出异常提示
raise FileNotFoundError(f'文件路径不存在:{abspath}')
# read_only:控制工作簿是否以只读模式打开,若为True,工作簿以只读模式打开,不允许对工作簿进行修改
self.workbook = load_workbook(self.file_path, read_only=False)
def read_entire_row(self, sheet_name='Sheet1', row_index=1):
"""
获取Excel文件一整行的数据
:param sheet_name: sheet页名称
:param row_index: 要返回哪一行的数据,索引从1开始
:return:
"""
try:
# 调用上面初始化的打开这个文件的对象 self.workbook 列表里面是获取哪一行它的名称
sheet = self.workbook[sheet_name]
# 列表推导式
rows_data = [cell.value for cell in sheet[row_index]]
return rows_data
except Exception as e:
logs.error(f'读取Excel文件一整行的数据数据异常,原因为:{e}')
finally:
self.close()
def read_multiple_rows(self, sheet_name='Sheet1'):
"""
读取Excel多行的数据,每一行数据组成一个列表
:param sheet_name: sheet页名称
:return: 返回list,例如:[['admin123','123456'],[],[],...]
"""
try:
# 在最外层定义一个空列表
all_rows_data = []
# 第一步跟上面一样,先拿到sheet这个对象
sheet = self.workbook[sheet_name]
# 调用 max_column 方法获取到最大的列数(行数 .max_row)
max_col = sheet.max_column
for row in sheet.iter_rows(min_row=1, max_row=sheet.max_row, min_col=1, max_col=max_col):
# row 是一个迭代器对象--但是不是需要获取的结果
# print(row)
# 列表推导式
row_data = [cell.value for cell in row]
# 调用append方法追加每一行的数据
all_rows_data.append(row_data)
return all_rows_data
except Exception as e:
logs.error(f'读取所有行数据异常,原因为:{e}')
finally:
self.close()
def read_entire_column(self, sheet_name='Sheet1', column_index=1):
"""
获取Excel文件一整列的数据
:param sheet_name: sheet页名称
:param column_index: 要返回哪一列的数据,索引从1开始
:return:
"""
column_data = []
try:
sheet = self.workbook[sheet_name]
for row in sheet.iter_rows(min_row=1, min_col=column_index, max_col=column_index):
column_data.append(row[0].value)
return column_data
except Exception as e:
logs.error(f'读取整列数据异常,原因为:{e}')
finally:
self.close()
def read_cell_value(self, row_index, column_index, sheet_name='Sheet1'):
"""
获取单元格的数据
:param sheet_name: sheet页名称(sheet_name='Sheet1' 关键字参数放到形式参数后面就不会有报错提醒了)
:param row_index: 行索引,从1开始
:param column_index: 列索引,从1开始
:return:
"""
try:
sheet = self.workbook[sheet_name]
# 直接调用获取单元格方法 sheet.cell
return sheet.cell(row=row_index, column=column_index).value
except Exception as e:
logs.error(f'读取单元格数据异常,原因为:{e}')
finally:
self.close()
def close(self):
"""关闭文件操作(释放内存空间资源)"""
self.workbook.close()
# 调试查看
if __name__ == '__main__':
# 实例化类--里面是文件路径
exl = ExcelDataReader('../../data/login_test.xlsx')
print(exl.read_cell_value(row_index=4, column_index=2))
11、最后都加上异常处理;其他别的方法可以根据测试数据格式是否需要继续增加(根据自己的需求去自定义);
其他
12、 列表解包(列表亦可以通过元组解包的方式进行解包里面的元素);
if __name__ == '__main__':
# 实例化类--里面是文件路径
exl = ExcelDataReader('../../data/login_test.xlsx')
# print(exl.read_multiple_rows())
data = ['admin123', '123456']
username, password = data
print(username, password)
# 运行结果
admin123 123456
进程已结束,退出代码为 0
13、若数据里面有三组数据,只想解包前面一组数据,后面两组还是一个列表;
data = ['admin123', '123456', '789']
username, *password = data
print(username, password)
# 运行结果
admin123 ['123456', '789']
进程已结束,退出代码为 0
Web UI 自动化测试数据驱动

未完待续。。。