什么是openpyxl?
openpyxl是python中专门进行excel数据读取与写入操作的第三方模块。使用openpyxl可以读取excel中的数据到代码中,然后进行相应的操作;还可以将数据写入excel中。但在接口自动化测试中,更多的是读取excel操作,写操作比较少。
openpyxl在框架中扮演什么样的角色?
接口测试的测试用例一般存放到excel中,openpyxl负责读取测试用例到python中,简单来说就是测试数据的搬运工。测试用例的data数据将作为接口的请求参数传给调取接口的方法中。
为什么接口测试用例要存放在excel当中?
第一、条理清晰,可读性好。为什么一般都用excel写测试用例?因为只要固定了表头的字段,后面的测试用例就可以接着表头写,像极了key:value的形式,a列的数据你看表头就知道这是测试用例的标题;b列的数据看表头就知道是测试用例的前置条件。
第二、 excel属于python容易读取的数据格式。python可以把excel所有的数据放进一个列表中,然后每一行再用一个列表来存储,就像下面这样:
[
[列:1,行:1],[列:1,行:2],[列:1,行:3],
[列:2,行:1],[列:2,行:2],[列:2,行:3]
……
]
这样python就很方便能读取excel中的数据,且也容易对数据进行操作。
接口测试用例怎么写?
一般接口自动化的测试用例包含表头的字段有:标题、请求方法、请求url地址、请求参数、预期结果。其中请求参数与预期结果最好为json格式,请求参数最好可以直接复制到postman等接口测试工具就可直接运行返回结果。
openpyxl的三个重要对象
workbook
工作簿对象。即excel文件:
初始化一个工作簿对象,让python知道你要操作的是哪个excel文件。调用openpyxl模块的load_workbook方法,传入excel的路径,即可初始化完成一个workbook对象。
#定义文件路径
file_path = os.path.dirname(__file__)
file_name = os.path.join(file_path,"cases.xlsx")
#初始化workbook对象
workbook = openpyxl.load_workbook(file_name)
print(workbook)
执行结果如下:
sheet
表单对象,即excel中的表单:
通过workbook[sheetname]即可初始化一个表单对象,告诉python你需要操作的是哪个表单里面的数据。
sheet_name = "register"
sheet = workbook["register"]
print(sheet)
执行结果如下:
cell
单元格对象。如下,其中一个单元格即为单元格对象。
调用sheet的cell方法,参数中指定行(row)和列(column)即可定位到对应的单元格。
需要注意的是,获取到了cell对象并非等于获取到了单元格的值,值只是单元格对象中的其中一个属性,它还有其他很多属性(长度、宽度、颜色等)。
调用cell对象的value属性才可获取单元格的值。
cell = sheet.cell(row=2, column=3)
print(cell)
print(cell.value)
操作结果如下:
代码实操
excel操作
获取某一行,某一列的单元格
# 获取某一行,某一列的单元格
# cell() 方法得到的是一个单元格对象,不是 case_id 值
cell = sheet.cell(row=2, column=3)
print("获取到的单元格对象为:{}".format(cell))
执行结果:
获取单元格的数据
cell = sheet.cell(row=2, column=3)
# 获取单元格的数据
print("获取到的单元格的值为:{}".format(cell.value))
执行结果:
获取所有行
#获取表单对象后,可通过它的rows属性获取所有行属性,通过生成器对象(generater)存储
rows = sheet.rows
print(rows)
执行结果:
由于生成器对象不能进行遍历,而经常要遍历表单中所有行获取所有的表单对象,进而获取它们的值,所以需要把生成器对象转换成list:
#把生成器对象转换成list
pprint.pprint(list(rows))
执行结果:
[(<Cell ‘register’.A1>,
<Cell ‘register’.B1>,
<Cell ‘register’.C1>,
(<Cell ‘register’.A2>,
<Cell ‘register’.B2>,
<Cell ‘register’.C2>,
(<Cell ‘register’.A3>,
<Cell ‘register’.B3>,
<Cell ‘register’.C3>,
(<Cell ‘register’.A4>,
<Cell ‘register’.B4>,
<Cell ‘register’.C4>,
(<Cell ‘register’.A5>,
<Cell ‘register’.B5>,
<Cell ‘register’.C5>,
(<Cell ‘register’.A6>,
<Cell ‘register’.B6>,
<Cell ‘register’.C6>,
(<Cell ‘register’.A7>,
<Cell ‘register’.B7>,
<Cell ‘register’.C7>,
(<Cell ‘register’.A8>,
<Cell ‘register’.B8>,
<Cell ‘register’.C8>,
(<Cell ‘register’.A9>,
<Cell ‘register’.B9>,
<Cell ‘register’.C9>,
(<Cell ‘register’.A10>,
<Cell ‘register’.B10>,
<Cell ‘register’.C10>,
(<Cell ‘register’.A11>,
<Cell ‘register’.B11>,
<Cell ‘register’.C11>,
(<Cell ‘register’.A12>,
<Cell ‘register’.B12>,
<Cell ‘register’.C12>,
(<Cell ‘register’.A13>,
<Cell ‘register’.B13>,
<Cell ‘register’.C13>,
(<Cell ‘register’.A14>,
<Cell ‘register’.B14>,
<Cell ‘register’.C14>)]
如上,通过list转换后,表单的所有行都存储到了list中,且每一行都通过元祖存储,每一行里是所有单元格对象。
获取表单中的所有单元格的数据
方法一:用列表存储每一行的值
"""
步骤:
一、获取表单中的所有行,这样数据格式就变成如下:
[(第一行所有cell对象),(第二行所有cell对象),(第三行所有cell对象)...]
二、遍历第一行开始的所有行;
三、遍历所有行中的每一行,通过cell.value属性获取每个单元格的值并存储到一个列表中;
四、用另一个列表存储所有行的数据。
"""
#定义文件路径
file_path = os.path.dirname(__file__)
file_name = os.path.join(file_path,"cases.xlsx")
#初始化workbook对象
workbook = openpyxl.load_workbook(file_name)
#print(workbook)
sheet_name = "register"
sheet = workbook["register"]
#print(sheet)
"""获取了表单对象后,可通过它的rows属性获取所有行属性。但sheet.rows获得的是一个生成器(generator)对象,无法进行遍历,所以需要转换成list.这里实际是做了第一步的工作,因为转换成列表后,已经把所有行对象存储到列表中了.
"""
rows = list(sheet.rows)
#定义一个列表接收所有单元格的值
data = []
#遍历所有的行对象.由于不需要编译标题,所以跳过第0行,从第一行开始遍历
for row in rows[1:]:
# 定义一个列表,存储每一行所有单元格的值
row_data = []
#遍历每一行中的所有单元格对象
for cell in row:
#获取每一个单元格对象的值,存储到row_data中
row_data.append(cell.value)
#把所有行的值存储到data中
data.append(row_data)
pprint.pprint(data)
执行结果:
方法二:用字典存储每一行的值
#定义文件路径
file_path = os.path.dirname(__file__)
file_name = os.path.join(file_path,"cases.xlsx")
#初始化workbook对象
workbook = openpyxl.load_workbook(file_name)
#print(workbook)
sheet_name = "register"
sheet = workbook["register"]
#print(sheet)
"""获取了表单对象后,可通过它的rows属性获取所有行属性。但sheet.rows获得的是一个生成器(generator)对象,无法进行遍历,所以需要转换成list.这里实际是做了第一步的工作,因为转换成列表后,已经把所有行对象存储到列表中了.
"""
rows = list(sheet.rows)
#定义一个列表接收所有单元格的值
data = []
#定义一个列表存储所有标题
tittles = []
#遍历第一行,取出第一行所有单元格的值
for tittle in rows[0]:
tittles.append(tittle.value)
#遍历第一行开始的所有行
for row in rows[1:]:
#定义一个字典,key为tittle,value为每一个单元格的值
row_data = {}
#遍历每一行,获取每一行所有单元格的值
for head,cell in enumerate(row):
"""
head = 0,tittles[0] = "case_id",cell = <Cell ‘register’.A2>;
head = 1,tittles[1] = "interface",cell = <Cell ‘register’.B2>;
head = 2,tittles[2] = "tittle",cell = <Cell ‘register’.C2>;
......
"""
row_data[tittles[head]] = cell.value
# 把所有行的值存储到data中
data.append(row_data)
pprint.pprint(data)
执行结果:
写入数据到excel中
单元格新增、修改值很简单,只需指定是哪个单元格,然后直接赋值即可。
#指定是哪个单元格
cell = sheet.cell(row=2, column=3)
print("单元格原来的值为:{}".format(cell.value))
#给单元格的value属性赋值
cell.value = "注册失败-密码错误"
print("修改后单元格的值为:{}".format(cell.value))
执行结果:
类封装
import openpyxl
import pprint
class excel_handler():
"""初始化实例参数"""
def __init__(self,filepath):
self.filepath = filepath
self.workbook = None
"""定义open_file方法,返回workbook对象"""
def open_file(self):
workbook = openpyxl.load_workbook(self.filepath)
self.workbook = workbook
return workbook
"""通过workbook对象获取sheet对象"""
def get_sheet(self,name):
workbook = self.open_file()
sheet = workbook[name]
return sheet
"""获取表单里的每一个单元格对象的value"""
def get_data(self,name):
#获取表单对象
sheet = self.get_sheet(name)
#获取表单对象中的所有行
rows = list(sheet.rows)
#定义一个列表,用来接收每一行的值
data = []
#定义一个列表,获取所有的标题
tittles = []
#遍历第一行rows[0],获取所有行的value属性,放入tittles中
for tittle in rows[0]:
tittles.append(tittle.value)
#遍历第二行后的所有数据(排除掉第一行是因为已经遍历完了第一行的标题)
for row in rows[1:]:
#定义一个字典,存放每一行的值,每一个值是一个键值对,key是标题,值是该行对应的value属性。
row_data = {}
#遍历拿到的每一行,获取每一行的每一个单元格放入row_data中.其中key为标题,value为该单元格对应的值.
for index,cell in enumerate(row):
row_data[tittles[index]] = cell.value
#把每一行的数据放入data中
data.append(row_data)
return data
"""对单元格的value属性赋值,写入到excel中"""
def write(self, sheet_name, row, column, data):
sheet = self.get_sheet(sheet_name)
sheet.cell(row, column).value = data
self.save()
self.close()
"""对excel做修改后,保存excel文件"""
def save(self):
self.workbook.save(self.file_path)
"""关闭workbook对象,释放内存"""
def close(self):
self.workbook.close()
if __name__ == '__main__':
excel = excel_handler("cases.xlsx")
pprint.pprint(excel.get_data("register"))