2.10.1 反射函数
反射函数概念:它可以把字符串映射到实例的变量或者实例的方法然后可以去执行调用、修改等操作。它有四个重要的方法:
• getattr 获取指定字符串名称的对象属性
• setattr 为对象设置一个对象
• hasattr 判断对象是否有对应的对象(字符串)
• delattr 删除指定属性
在数据驱动中使用的是getattr方法,通过读取excel表格的数据确定关键字和参数,执行对应的代码。先看下语法:
func=(obj,method_name)
func(*args)
obj:关键字类对象
method_name:关键字方法
args:方法中需要的参数
示例:
class A:
def func1(self):
print("方法一")
def func2(self,a:str=''):
print("方法2"+a)
def func3(self,a,b):
print("两数之和为"+str(a+b))
#创建A类的对象
a=A()
method=input("请输入方法名")
params=input("请输入参数")
try:
f=getattr(a,method)
except:
print("方法不存在")
if params:
f(*params)
else:
f()
结果:
请输入方法名func2
请输入参数1
方法21
2.10.2 原始数据驱动
1.excel方法
需要安装的python库:
openpyxl、xlrd、xlwt
Excel.py:根据文件结尾xlsx、xls,设置打开或写入excel的对象
NewExcel.py:文件结尾xlsx的excel文件处理方法
OldExcel.py:文件结尾xls的excel文件处理方法
说明:这三个文件不是我写的 这里我把原代码放出来就不上注释了 抱歉!
Excle.py文件内容:
import os
from common.excel import NewExcel
from common.excel import OldExcel
def get_reader(srcfile=''):
reader = None
if not os.path.isfile(srcfile):
print("%s not exist!" % (srcfile))
return reader
if srcfile.endswith('.xls'):
reader = OldExcel.Reader()
reader.open_excel(srcfile)
return reader
if srcfile.endswith('.xlsx'):
reader = NewExcel.Reader()
reader.open_excel(srcfile)
return reader
def get_writer(srcfile, dstfile):
writer = None
if not os.path.isfile(srcfile):
print("%s not exist!" % (srcfile))
return writer
if srcfile.endswith('.xls'):
writer = OldExcel.Writer()
writer.copy_open(srcfile, dstfile)
return writer
if srcfile.endswith('.xlsx'):
writer = NewExcel.Writer()
writer.copy_open(srcfile, dstfile)
return writer
NewExcle.py文件内容:
import os, openpyxl
from shutil import copyfile
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment, Protection
class Reader:
def __init__(self):
self.workbook = None
self.sheet = None
self.rows = 0
self.r = 0
# 打开excel
def open_excel(self, srcfile):
if not os.path.isfile(srcfile):
print("%s not exist!" % (srcfile))
return
openpyxl.Workbook.encoding = "utf8"
self.workbook = openpyxl.load_workbook(filename=srcfile)
self.sheet = self.workbook[self.workbook.sheetnames[0]]
self.rows = self.sheet.max_row
self.r = 0
return
def get_sheets(self):
sheets = self.workbook.sheetnames
return sheets
def set_sheet(self, name):
self.sheet = self.workbook[name]
self.rows = self.sheet.max_row
self.r = 0
return
def readline(self):
lines = []
for row in self.sheet.rows:
line = []
for cell in row:
if cell.value is None:
line.append('')
else:
line.append(cell.value)
lines.append(line)
return lines
class Writer:
def __init__(self):
self.workbook = None
self.wb = None
self.sheet = None
self.df = None
self.row = 0
self.clo = 0
def copy_open(self, srcfile, dstfile):
if not os.path.isfile(srcfile):
print(srcfile + " not exist!")
return
if os.path.isfile(dstfile):
print(dstfile + " file already exist!")
self.df = dstfile
self.workbook = openpyxl.load_workbook(filename=srcfile)
copyfile(srcfile, dstfile)
self.wb = openpyxl.load_workbook(filename=dstfile)
return
def get_sheets(self):
sheets = self.workbook.sheetnames
return sheets
def set_sheet(self, name):
self.sheet = self.wb[name]
return
def write(self, r, c, value, color=None):
d = self.sheet.cell(row=r + 1, column=c + 1, value=value)
if color:
if color == 0:
color = "FF000000"
elif color == 1:
color = "FFFFFFFF"
elif color == 2:
color = "FFFF0000"
elif color == 3:
color = "FF00FF00"
elif color == 4:
color = "FF0000FF"
elif color == 5:
color = "FFFFFF00"
else:
color = "FF000000"
font = Font(name='Arial',
size=11,
bold=False,
italic=False,
vertAlign=None,
underline='none',
strike=False,
color=color)
d.font = font
return
def save_close(self):
self.wb.save(self.df)
return
OldExcle.py文件内容:
import os, xlrd, xlwt
from xlutils.copy import copy
class Reader:
def __init__(self):
self.workbook = None
self.sheet = None
self.rows = 0
self.r = 0
def open_excel(self, srcfile):
if not os.path.isfile(srcfile):
print("%s not exist!" % (srcfile))
return
xlrd.Book.encoding = "utf8"
self.workbook = xlrd.open_workbook(filename=srcfile)
self.sheet = self.workbook.sheet_by_index(0)
self.rows = self.sheet.nrows
self.r = 0
return
def get_sheets(self):
sheets = self.workbook.sheet_names()
return sheets
def set_sheet(self, name):
self.sheet = self.workbook.sheet_by_name(name)
self.rows = self.sheet.nrows
self.r = 0
return
def readline(self):
lines = []
while self.r < self.rows:
row1 = None
row = self.sheet.row_values(self.r)
self.r = self.r + 1
i = 0
row1 = row
for strs in row:
row1[i] = str(strs)
i = i + 1
lines.append(row1)
return lines
class Writer:
def __init__(self):
self.workbook = None
self.wb = None
self.sheet = None
self.df = None
self.row = 0
self.clo = 0
def copy_open(self, srcfile, dstfile):
if not os.path.isfile(srcfile):
logger.error(srcfile + " not exist!")
return
if os.path.isfile(dstfile):
print(dstfile + " file already exist!")
self.df = dstfile
self.workbook = xlrd.open_workbook(filename=srcfile, formatting_info=True)
self.wb = copy(self.workbook)
return
def get_sheets(self):
sheets = self.workbook.sheet_names()
return sheets
def set_sheet(self, name):
self.sheet = self.wb.get_sheet(name)
return
def write(self, r, c, value, color=None):
def _getCell(sheet, r, c):
row = sheet._Worksheet__rows.get(r)
if not row:
return None
cell = row._Row__cells.get(c)
return cell
cell = _getCell(self.sheet, r, c)
if cell:
idx = cell.xf_idx
if color is None:
self.sheet.write(r, c, value)
if cell:
ncell = _getCell(self.sheet, r, c)
if ncell:
ncell.xf_idx = idx
else:
style = xlwt.XFStyle()
font = xlwt.Font()
font.name = 'Arial'
font.bold = True
# font.underline = True
# font.italic = True
font.colour_index = color
style.font = font
borders = xlwt.Borders()
borders.left = xlwt.Borders.THIN
borders.right = xlwt.Borders.THIN
borders.top = xlwt.Borders.THIN
borders.bottom = xlwt.Borders.THIN
style.borders = borders
self.sheet.write(r, c, value, style)
return
def save_close(self):
self.wb.save(self.df)
return
2.读取excel用例,执行用例,将结果写入excel
示例代码:
#关键字对象
web=Web()
def runcase(obj,line,i):
"""
:param obj:关键字对象
:param line:参数
:param i: 写入的行
:return:
"""
#思路,先判断哪一行是要进行反射的,
#如果第一个或者第二个有值则不执行反射
print(line)
if len(line[0])>1 or len(line[1])>1:
return
try:
func=getattr(obj,line[3])
print(line[3])
writer.write(i,7,"PASS",3)
except Exception as e:
print('关键字%s不存在' % line[3])
writer.write ( i, 7, "FALl", 2 )
return
params=line[4:]
params=params[:params.index('')]
if params:
func(*params)
else:
func()
#打开文件
reader=get_reader("../lib/电商项目用例.xlsx")
#写入文件
writer=get_writer("../lib/电商项目用例.xlsx","../lib/result-电商项目用例.xlsx")
#获取内容,获取sheet页 然后输出每一个sheet页每一行的数据,在把每一行的数据进行遍历
#调用get_sheets方法调用
#执行成功写入pass
sheets=reader.get_sheets()
for i in range (0,len(sheets)):
#遍历sheets名称,挨个读取
reader.set_sheet(sheets[i])
#保证读取和写入都在同一个sheet页
writer.set_sheet(sheets[i])
lines=reader.readline()
#输出每一行的信息
for i in range(1,len(lines)):
runcase(web,lines[i],i)
#保存结果
writer.save_close()
2.10.3 pytest集成excel
思路:将excel中的用例保存到列表cases中,使用pytest参数化调用cases,再用反射的方式执行cases。就实现了excel驱动pytest。
代码供参考:
保存用例到cases:
class Conf:
def __init__(self,reader_path="./../lib/电商项目用例.xlsx",writer_path="./../lib/result-电商项目用例.xlsx"):
#读取excel文件
self.reader=get_reader(reader_path)
#self.writer=get_writer(reader_path,writer_path)
#获取sheet名称
self.sheetname=self.reader.get_sheets()
#设置cases 保存所有用例
self.cases=[]
self.get_Case()
def get_Case(self):
#设置要读取的sheet页
for i in range(0,len(self.sheetname)):
self.reader.set_sheet(self.sheetname[i])
case=[]
#读取行
lines=self.reader.readline()
for i in range (1,len(lines)):
line=lines[i]
# 如果一个数据有值 我们不做任何操作
if len(line[0])>1:
pass
#如果第二个数据有值我们开始保存case,这是一个case的开始 登录失败的用例
elif len(line[1])>1:
#如果不是第一行 到了第二个用例的时候
if i >2 :
#我们要把上一个用例保存到cases里面
self.cases.append(case)
#将case置空保存第二条用例
case=[]
case.append(line)
#如果没有值 就直接在case后面增加,直到下一次 len(line[1])>1
else:
case.append(line)
#把最后一个用例保存到cases
self.cases.append(case)
#输出case
# for i in range (0,len(self.cases)):
# print(self.cases[i])
conf=None
用例部分代码:
class Test_web():
"""web自动化测试类"""
def setup_class(self):
self.web=Web()
allure.step()
@pytest.mark.parametrize("case_params",excel_conf.conf.cases)
def test_case(self,case_params):
for i in range (0,len(case_params)):
line=case_params[i]
#判断那行执行
if len(line[0]) > 1 or len(line[1]) > 1:
continue
#获取一行的数据
try:
func =getattr(self.web,line[3])
params = line[4:]
params = params[:params.index('')]
func(*params)
except:
print(line[3]+"方法不存在")
if __name__=='__main__':
excel_conf.conf=Conf()
os.system('rd /s/q result')
os.system('rd /s/q reports')
pytest.main(['-s', 'pytest_example/test_web.py','--alluredir', 'result'])
os.system('allure generate result -o reports --clean')
再使用pytest生成allure报告,这里就不介绍allure的设计了(我比较懒)。