python接口测试框架实战与自动化进阶
一、从接口自动化框架设计到开发
1、如何设计一个接口自动化测试框架
2、python操作excel获得内容
安装依赖:
pip install xlwt # 用于写Excel文件
pip install xlrd # 用于读取Excel文件
Python对Excel的读写主要有xlrd、xlwt、xlutils、openpyxl、xlsxwriter几种:
- xlrd主要是用来读取excel文件
- xlwt主要是用来写excel文件
- xlutils结合xlrd可以达到修改excel文件目的
- openpyxl可以对excel文件进行读写操作
- xlsxwriter可以写excel文件并加上图表
1)python 对Excel文件的基本操作:
# -*- coding: utf-8 -*- import xlrd import xlwt from datetime import date,datetime def read_excel(): # 打开文件 workbook = xlrd.open_workbook(r'F:\demo.xlsx') # 获取所有sheet workbook.sheet_names() # [u'sheet1', u'sheet2'] sheet2_name = workbook.sheet_names()[1] # 根据sheet索引或者名称获取sheet内容 sheet2 = workbook.sheet_by_index(1) # sheet索引从0开始 sheet2 = workbook.sheet_by_name('sheet2') # sheet的名称,行数,列数 sheet2.name,sheet2.nrows,sheet2.ncols # 获取整行和整列的值(数组) rows = sheet2.row_values(3) # 获取第四行内容 cols = sheet2.col_values(2) # 获取第三列内容 print rows print cols # 获取单元格内容 sheet2.cell(1,0).value.encode('utf-8') sheet2.cell_value(1,0).encode('utf-8') sheet2.row(1)[0].value.encode('utf-8') # 获取单元格内容的数据类型 sheet2.cell(1,0).ctype if __name__ == '__main__': read_excel()
demo:
封装获取excel表数据相关操作:
import xlrd class OperationExcel: def __init__(self,file_name=None,sheet_id=None): if file_name: self.file_name = file_name self.sheet_id = sheet_id else: self.file_name = '../media/excel_dir/case1.xls' self.sheet_id = 0 self.data = self.get_data() # 获取sheets内容 def get_data(self): data = xlrd.open_workbook(self.file_name) # 打开excel文件 tables = data.sheets()[self.sheet_id] # 获取excel文件内容句柄,sheet对象 return tables # 获取单元格行数 def get_lines(self): return self.data.nrows # 获取某一单元格的内容 def get_cell_value(self,row,col): return self.data.cell_value(row,col) if __name__ == '__main__': opers = OperationExcel()
3、操作json文件
在目录中找到json文件,通过代码操作,获取json文件内指定的数据:
import json class OperationJson: def __init__(self,file_name = None): if file_name: self.file_name = file_name else: self.file_name = '../media/json_dir/cookie.json' self.data = self.read_data() # 读取json文件的数据 def read_data(self): with open(self.file_name) as fp: data = json.load(fp) return data # 根据关键字获取数据 def get_data(self,key): return self.data[key] if __name__ == '__main__': opjson = OperationJson()
4、封装获取常量方法
class global_var: #case_id Id = '0' # id request_name = '1' # 模块 url = '2' # url run = '3' # 是否运行 request_way = '4' # 请求类型 header = '5' # 是否携带header case_depend = '6' # case依赖 ... data_depend = '7' field_depend = '8' data = '9' expect = '10' result = '11' #获取caseid def get_id(): return global_var.Id #获取url def get_url(): return global_var.url def get_run(): return global_var.run def get_run_way(): return global_var.request_way def get_header(): return global_var.header def get_case_depend(): return global_var.case_depend def get_data_depend(): return global_var.data_depend def get_field_depend(): return global_var.field_depend def get_data(): return global_var.data def get_expect(): return global_var.expect def get_result(): return global_var.result def get_header_value(): return global_var.header
5、封装获取接口数据
- 上面通过封装excel表,提供了python excel表相关的操作:operation_excel.py 文件
- 同时提供了关键字查询json文件数据的相关操作:operation_json.py 文件
- 另外配置了excel表中各列的序号,现在我们来设计接口数据封装:data_config.py
我们的目的是拿到excel表中,每个指定的单元格的数据:
- 通过 data_config.py内部的封装操作,拿到excel表的各列序号 ;
- 通过operation_excel.py内部封装的get_cell_value() 方法拿到指定单元格的数据,前提需传入行参数 ;
- 通过operation_json.py内部封装的get_data方法,可以拿到json格式的请求数据
通过上面的操作,我们只需要传入行参数,即第几行,并指定调用对应方法,就是获取想要获取到的单元格数据,实现代码如下:
from util.operation_excel import OperationExcel from . import data_config from util.operation_json import OperationJson class GetData: # 获取数据 def __init__(self): self.opera_excel = OperationExcel() # 实例化 OperationExcel ,默认操作的excel表:../media/excel_dir/case1.xls # 获取excel行数,就是我们的case个数 def get_case_lines(self): return self.opera_excel.get_lines() #获取是否执行 yes or no def get_is_run(self,row): flag = None col = int(data_config.get_run()) #第col列 run_model = self.opera_excel.get_cell_value(row,col) # 拿到row col 指定的单元格数据 if run_model == 'yes': flag = True else: flag = False return flag #是否携带header def is_header(self,row): col = int(data_config.get_header()) header = self.opera_excel.get_cell_value(row,col) if header != '': return header else: # 没有携带header return None #获取请求方式 get or post def get_request_method(self,row): col = int(data_config.get_run_way()) request_method = self.opera_excel.get_cell_value(row,col) return request_method #获取url def get_request_url(self,row): col = int(data_config.get_url()) url = self.opera_excel.get_cell_value(row,col) return url #获取请求数据 request_data def get_request_data(self,row): col = int(data_config.get_data()) data = self.opera_excel.get_cell_value(row,col) if data == '': return None return data #通过获取关键字拿到data数据(是个字段) ,存于json文件中 def get_data_for_json(self,row): opera_json = OperationJson() request_data = opera_json.get_data(self.get_request_data(row)) return request_data #获取预期结果 def get_expcet_data(self,row): col = int(data_config.get_expect()) expect = self.opera_excel.get_cell_value(row,col) if expect == '': return None return expect
6、 post、get基类的封装
import requests import json class RunMethod: def post_main(self,url,data,header=None): res = None if header != None: res = requests.post(url=url,data=data,headers=header) else: res = requests.post(url=url,data=data) return res.json() def get_main(self,url,data=None,header=None): res = None if header != None: res = requests.get(url=url,data=data,headers=header,verify=False) else: res = requests.get(url=url,data=data,verify=False) return res.json() def run_main(self,method,url,data=None,header=None): res = None if method == 'Post': res = self.post_main(url,data,header) else: res = self.get_main(url,data,header) return json.dumps(res,ensure_ascii=False)
7、主程序封装,程序启动在此文件启动
from base.runmethod import RunMethod from data.get_data import GetData from util.operation_json import OperationJson class RunTest: def __init__(self): self.run_method = RunMethod() # 实现get/post方法的类实例 self.data = GetData() # 获取excel表数据的类实例 #程序执行的 def go_on_run(self): res = None rows_count = self.data.get_case_lines() # case个数 for i in range(1,rows_count): is_run = self.data.get_is_run(i) # 是否run ,excel表中查询 if is_run: url = self.data.get_request_url(i) method = self.data.get_request_method(i) request_data = self.data.get_data_for_json(i) print("request_data:",request_data) header = self.data.is_header(i) res = self.run_method.run_main(method,url,request_data,header) print(res) return res if __name__ == '__main__': run = RunTest() run.go_on_run()
8、通过预期结果判断case是否执行成功
在common_uil.py中新建类:CommonUtil,
定义 is_contain() 方法,用于判断 预测结果 跟实际结果是否一致 ,若一致 测试通过;如不一致 测试失败
class CommonUtil: def is_contain(self,str_one,str_two): ''' 判断一个字符串是否在另外一个字符串中 str_one:查找的字符串 str_two:被查找的字符串 ''' flag = None if str_one in str_two: flag = True else: flag = False return flag
9、将测试结果写入到excel表中
1)在operation_excel.py文件的OperationExcel类中添加新方法:write_value() , 用于将数据写入到Excel表中:
def write_value(self, row, col, value): ''' 写入excel数据 需要值:row,col,value ''' read_data = xlrd.open_workbook(self.file_name) # 打开excel文件 write_data = copy(read_data) # 拿到excel内容句柄 sheet_data = write_data.get_sheet(0) # 复制文件,让xlutils相关处理 sheet_data.write(row, col, value) # 将数据写入到ex文件的指定单元格中 write_data.save(self.file_name) # 保存
2)在get_data.py文件中的GetData类,添加write_result() 方法,用于调用 1)中的write_value方法,将数据写入到excel表中:
# 调用excel write方法,将测试结果写入到excel表中 def write_result(self,row,value): col = int(data_config.get_result()) self.opera_excel.write_value(row,col,value)
3)最后在run_test.py中的主程序中,进行判断:预测结果跟实际结果是否一致?一致则测试通过,不一致则测试失败:
if self.com_util.is_contain(expect,res): self.data.write_result(i, 'pass') else: self.data.write_result(i, 'fail')
10、python email :发送邮件
import smtplib from email.mime.text import MIMEText from email.header import Header class SendEmail: def __init__(self,receivers = None): self.mail_host = "smtp.163.com" # 设置服务器 self.mail_user = "13*****657@163.com" # 用户名 self.mail_pass = "******" # 密令/密码 self.sender = '13******657@163.com' if receivers: self.receivers = receivers else: self.receivers = ['8******9@qq.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱 def email_init(self,content,): message = MIMEText(content, _subtype='plain', _charset='utf-8') # 邮件内容 subject = '接口自动化测试报告' message['Subject'] = Header(subject, 'utf-8') # 邮件主题 message['From'] = self.sender # 发送人,必填,邮箱格式 message['To'] = ";".join(self.receivers) # 收件人,必填,邮箱格式 server = smtplib.SMTP() server.connect(self.mail_host, 25) # 连接服务器 server.login(self.mail_user, self.mail_pass) # 登录 try: server.sendmail(self.sender, self.receivers, message.as_string()) print('发送成功') except smtplib.SMTPException as e: print("Error: 无法发送邮件") server.close() def send_email(self,pass_list,fail_list): pass_num = float(len(pass_list)) # 成功个数 fail_num = float(len(fail_list)) # 失败个数 count_num = pass_num + fail_num # 总数 pass_result = "%.2f%%" % (pass_num / count_num * 100) # 成功率 fail_result = "%.2f%%" % (fail_num / count_num * 100) # 失败率 content = "此次一共运行接口个数为%s个,通过个数为%s个,失败个数为%s,通过率为%s,失败率为%s" %(count_num,pass_num,fail_num,pass_result,fail_result ) self.email_init(content) if __name__ == "__main__": send_email = SendEmail() send_email.send_email([1,3,5,7],[2,4,6])
未来的你,会感谢现在努力的你!