python自动化框架(一)
一、jsonpath难点分析
dic = {
"error_code": 0,
"stu_info": [
{
"id": 2057,
"name": "xiaohei",
"sex": "nan",
"age": 29,
"addr": "beijing",
"grade": "tianxie",
"phone": "18712321234",
"gold": 100
}
]
}
import jsonpath
s = jsonpath.jsonpath(dic,'$..error_code')
print(s) # seqs=['!=','>=','<=','=','<','>','in','notin']
# #list循环这种的话,写用例的时候简单
# s1='error_code=0,name!=xxx,age>18'
# #[error_code>=0 , name!=xxx,age>1]
# s1_list = s1.split(',')
# format_list=[]
# for s in s1_list:
# #erro_code=0 [error_code,0]
# #name!=xxx
# for seq in seqs:
# # = != >=
# if seq in s:
# key,value = s.split(seq)
# tmep = [key,seq,value]
# format_list.append(tmep)
# break
# #[[error_code,'=',0] ]
#
# print('format_list',format_list) #s='erro_code:=:0,name:!=:xxx,age:>:18'
#这种写代码的时候简单 erro_code = 0 # error_code=0
# name!=xxx
# age>18
# < >= in <= notin 二、实现参数化
封装好的requests:
import requests
import nnlog
import os
from conf.setting import LOG_PATH
class MyRequest:
log_file_name = os.path.join(LOG_PATH,'MyRequest.log')#日子文件名
time_out = 10 #请求超时时间
def __init__(self,url,data=None,headers=None,file=None):
self.url = url
self.data = data
self.headers = headers
self.file = file
def post(self):
try:
req = requests.post(self.url,data=self.data,headers=self.headers,
files=self.file,timeout=self.time_out)
except Exception as e:
res = {"status":0,"data":e.args} #0代表请求失败
else:
try:
res = {"status":1,"data":req.json()} #1代表返回的json
except Exception as e:
res = {"staus":2,"data":req.text} #2代表返回不是json
log_str = 'url: %s 请求方式:post data:%s ,返回数据:%s'%(self.url,self.data,res)
self.write_log(log_str)
return res def get(self):
try:
req = requests.get(self.url,params=self.data,headers=self.headers,timeout=self.time_out)
except Exception as e:
res = {"status":0,"data":e.args} #0代表请求失败
else:
try:
res = {"status":1,"data":req.json()} #1代表返回的json except Exception as e:
res = {"staus":2,"data":req.text} #2代表返回不是json
log_str = 'url: %s get请求 data:%s ,返回数据:%s'%(self.url,self.data,res)
self.write_log(log_str)
return res @classmethod
def write_log(cls,content):
log = nnlog.Logger(cls.log_file_name)
log.debug(content) case operation:
import xlrd
from core.my_requests import MyRequest
def get_case(path):
'''
:param path: excel测试用例
:return: 二维数组,每一个里面是一条测试用例
'''
all_case = []
book = xlrd.open_workbook(path)
sheet = book.sheet_by_index(0)
for i in range(1,sheet.nrows):
row_data = sheet.row_values(i)[4:8]
all_case.append(row_data)
return all_case def send_request(url,method,data,headers=None):
req = MyRequest(url,data,headers=headers)
if method.upper()=="POST":
res = req.post()
elif method.upper() =='GET':
res = req.get()
else:
res = {"data":"暂时不支持该方法!"}
return res['data'] tools方法:
import random
import string
import time
class ParseParam:
func_map = ['phone','email','id_card','cur_time','money']
#映射函数的
def __init__(self,param):
self.param = param
self.parse()
def phone(self):
phone_starts = ['134','181','138','177','150','132','188','186','189','130','170','153','155']
start = random.choice(phone_starts)
end = str(random.randint(0,99999999))
res = start+ end.zfill(8)
return res
def email(self):
email_end=['163.com','qq.com','126.com','sina.com']
end = random.choice(email_end)
start_str='ATP_test_'
email_start = ''.join(random.sample(string.ascii_letters+string.digits,6))
return start_str+email_start+'@'+end
def id_card(self):
'''这个产生身份证号的'''
return 410881199011212121
def cur_time(self):
return int(time.time())
def money(self):
return 10000
def parse(self):
for func in self.func_map:
temp = str(getattr(self,func)()) #手机号
#<phone>,186122323
#<email> ,sdfsdfs@163.com
self.param = self.param.replace('<%s>'%func,temp)
# s='abc'
# s.replace('abc','123') def strToDict(self):
data ={}
pl =self.param.split(',')
for p in pl:
temp = p.split('=')
if len(temp)>1:
key,value =temp
data[key] =value
return data if __name__ == '__main__': param = 'username=niuhanyang' \
'&phone=<phone>&email=<email>' \
'&id_card=<id_card>&start_time=' \
'<cur_time>,balan=<money>'
p = ParseParam(param)
print(p.param)
# print(p.phone())
# res = getattr(p,'money') #获取一个对象里面的属性(方法、变量) # # print(res())
# import os,requests
# res = hasattr(requests,'get')#判断某个模块、类下面有没有某个方法或者变量
# print(res) parse_response
import jsonpath
class ResponseParse:
seqs = ['!=', '>=', '<=', '=', '<', '>', 'in', 'notin']
def __init__(self,response,check):
self.response = response
self.check = check
def format_check(self):
#格式化检查信息,分别列出key 运算符 实际结果
#会返回 [['error_code','=','0'],['name','!=','xxx']]
format_list = []
check_list = self.check.split(',')
for s in check_list:
for seq in self.seqs:
if seq in s:
if len(s.split(seq))>1:
key, value = s.split(seq)
temp = [key, seq, value]
format_list.append(temp)
break
return format_list def get_real_value(self,key):
#从字典里面获取key对应的value
res = jsonpath.jsonpath(self.response,'$..%s'%key)
#$..%s这个是jsonpath这个模块的用法
if res:
return res[0]
return '找不到该key【%s】'%key
def operation_check(self,real,seq,hope):
#根据运算符判断结果
msg = "判断信息:%s %s %s "%(real,seq,hope)
real = str(real)#为了保持类型一致
if seq=='=':
status = real == hope
elif seq=='!=':
status = real != hope
elif seq =='in':
status = real in hope
elif seq =='notin':
status = real not in hope
else:
status,msg = self.num_check(real,seq,hope)
return status,msg def num_check(self,real,seq,hope): msg = "判断信息:%s %s %s "%(real,seq,hope)
try:
real=float(real)
hope=float(hope)
except Exception as e:
msg = "比较时出错,大小比较只能是数字类型!" \
"%s %s %s"%(real,seq,hope)
status = False
else:
if seq=='>':
status = real > hope
elif seq =='<':
status = real < hope
elif seq == '<=':
status = real <= hope
else:
status = real >= hope
return status,msg
def check_res(self):
#校验所有的检查点
check_list = self.format_check()
#[['error_code','=','0'],['name','!=','xxx']]
all_msg=''
for check in check_list:
key,seq,hope = check
real = self.get_real_value(key)
status,msg = self.operation_check(real,seq,hope)
all_msg = all_msg+msg+'\n' #累加提示信息
if status:
pass
else:
return '失败',all_msg
return '通过',all_msg 获取返回结果输出报告
import xlrd
from xlutils.copy import copy
import os
import datetime
from conf import setting
import yagmail
def make_today_dir():
#创建当天的文件夹,返回绝对路径
today = str(datetime.date.today())
#c:/xxx/xxx/atp/report/2018-11-24/测试用例.xls
abs_path = os.path.join(setting.REPORT_PATH,today)
#拼成当天的绝对路径
if os.path.exists(abs_path):
pass
else:
os.mkdir(abs_path) return abs_path def write_res(case_path,case_res):
#c:/xxx/xxx/atp/cases/测试用例.xls
#[ ['{"xdfsdf}','通过'],['{"xdfsdf}','失败'] ]
book = xlrd.open_workbook(case_path)
new_book = copy(book)
sheet = new_book.get_sheet(0)
for row,res in enumerate(case_res,1):
response,status = res
sheet.write(row,8,response)
sheet.write(row,9,status)
#写第8列和第9列
cur_date_dir = make_today_dir()#创建当前文件夹,并且返回绝对路径
file_name = os.path.split(case_path)[-1] #只获取到filename
cur_time = datetime.datetime.today().strftime('%H%M%S') #获取到当天时分秒
new_file_name = cur_time+'_'+file_name #165530_测试用例.xls
real_path = os.path.join(cur_date_dir,new_file_name)#拼路径
new_book.save(real_path)
return real_path def send_mail(content,file_path=None):
#发邮件,传入邮件正文和附件
m = yagmail.SMTP(**setting.MAIL_INFO,)
subject = '接口测试报告_%s'%str(datetime.datetime.today())
m.send(subject=subject,to=setting.TO,contents=content,attachments=file_path)
#1、检查点解析完成
#2、取到实际的值
#
s='error_code=0,name!=xxx,age>18' print(type(s[-1])) {
"error_code": 0,
"name": "小黑",
"stu_info": {
"age": 18
}
}
串联起来
import os,sys
BAE_PATH = os.path.dirname(
os.path.dirname(os.path.abspath(__file__))
) #atp的目录
sys.path.insert(0,BAE_PATH) from conf.setting import CASE_PATH
from core import case_operation,parse_param,parse_response
from core import tools
import glob
class RunCase:
content = '''
各位好!
本次测试结果:总共运行%s条用例,通过%s条,失败%s条。详细信息见附件。
'''
def get_excel(self):
#s='/Users/nhy/test*.xls'
for excel in glob.glob(os.path.join(CASE_PATH,'test*.xls')):
cases = case_operation.get_case(excel)#调用读取excel的函数
results = self.send_requests(cases) #发送请求,并校验结果
report_file_path = tools.write_res(excel,results)#写入结果
all_count = len(cases) #总共多条用例
fail_count = all_count - self.success_count
content = self.content%(all_count,self.success_count,fail_count)
tools.send_mail(content,report_file_path)
def send_requests(self,cases):
# #[[url,get,data,check],[url,get,data,check]]
self.success_count = 0
results = []
for case in cases:
url,method,param,check = case #获取到每条用例的参数
p = parse_param.ParseParam(param) #解析请求参数
data = p.strToDict()#请求参数转成字典
response = case_operation.send_request(url,method,data)#发请求
#下面这2行代码是判断用例执行是否通过的
p2 = parse_response.ResponseParse(response,check)
status, msg = p2.check_res()#调用写好的校验结果方法,
real_res = str(response)+'\n'+msg #是把校验的信息和返回的json拼到一起
results.append([real_res,status]) #这里面的小list是每一个用例运行的结果
if status == '通过':
self.success_count += 1 #统计成功的次数
return results #返回运行的结果 def main(self):
print('开始测试'.center(50,'*'))
self.get_excel()
print('测试结束'.center(50,'*')) if __name__ == '__main__':
run = RunCase()
run.main()
python自动化框架(一)的更多相关文章
- python自动化框架(unnitest+selenium+htmlreport)
上一篇零零散散的写了一些python unnitest的一些知识,这里讲讲我在实际中使用到的自动化测试框架,算是上篇记录的补充!其实我觉得:什么框架都无所谓,关键是当如果用你的框架发现了bug,能尽量 ...
- selenium+python自动化框架
流程: 环境准备 eclipse :需安装pydev.testng插件 python :安装python完成后,需 pip下安装selenium:命令: pip install selenium 我现 ...
- python自动化框架nose
python除了unittest,还有一款更快捷的nose,nose可以说是对unittest的一种简化吧 但是他不需要unittest那种必须有固有的格式,他只需要文件,类名,方法名等含有test就 ...
- python自动化测试(3)- 自动化框架及工具
python自动化测试(3) 自动化框架及工具 1 概述 手续的关于测试的方法论,都是建立在之前的文章里面提到的观点: 功能测试不建议做自动化 接口测试性价比最高 接口测试可以做自动化 后面所谈到 ...
- python+request接口自动化框架
python+request接口自动化框架搭建 1.数据准备2.用python获取Excel文件中测试用例数据3.通过requests测试接口4.根据接口返回的code值和Excel对比 但本章只讲整 ...
- 转载:python + requests实现的接口自动化框架详细教程
转自https://my.oschina.net/u/3041656/blog/820023 摘要: python + requests实现的接口自动化框架详细教程 前段时间由于公司测试方向的转型,由 ...
- 【转】基于Selenium的web自动化框架(python)
1 什么是selenium Selenium 是一个基于浏览器的自动化工具,它提供了一种跨平台.跨浏览器的端到端的web自动化解决方案.Selenium主要包括三部分:Selenium IDE.Sel ...
- ShutIt:一个基于 Python 的 shell 自动化框架
ShutIt是一个易于使用的基于shell的自动化框架.它对基于python的expect库(pexpect)进行了包装.你可以把它看作是“没有痛点的expect”.它可以通过pip进行安装. Hel ...
- python + requests实现的接口自动化框架详细教程
前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行的接口测试,后来,组内有人讲原先web自动化的测试框架移驾成接口的自 ...
随机推荐
- 帝国cms中当调用当前信息不足时,继续取其他数据
<?php$sql=$empire->query("select * from table1 order by id limit 20"); $num = mysql_ ...
- java接口特性
java接口特性 (1)接口可以被实例化 ,常作为类型使用 (2)实现类必须实现接口的所有方法 ,抽象类除外 (3)实现类可以实现多个几口 java中的多继承 (4)接口中的变量都是静态变量
- 在form表单里上传图片
需要上传多个图片分别上传,本来提供的工具类里上传一张可以form表单对象实现 后台用MultipartFile file var formdata = new FormData($("#in ...
- Django知识总结(二)
拾 ● 模型(M) 一 ● ORM(对象关系映射, Object Relational Mapping) 类----一张表 类的实例对象----表中的一条记录 映射关系 ①python的类名对应的SQ ...
- 活代码LINQ——07
来源说明:https://blog.csdn.net/sha574810590/article/details/40738069 在LINQ中,数据源和查询结果实际上都是IEnumerable< ...
- iOS 判断一个类是否存在,NSStringFromClass 不用 import 就可以获取类
Class myCls = NSClassFromString(@"Person"); NSString *str = NSStringFromClass(myCls); if ( ...
- SecureCRT通过SSH2协议远程登录Ubuntu 18.04的过程总结
reference: https://blog.csdn.net/ghostar03/article/details/47441715 https://blog.csdn.net/u011186256 ...
- nodejs03-GET数据处理
数据请求:--- 前台:form ajax jsonp 后台:一样 请求方式: 1.GET 数据在URL中 2.POST 数据在请求体中 请求数据组成: 头--header:url,头信息 身子--c ...
- error: ‘module’ object has no attribute ‘_rebuild_tensor_v2’
import torch._utils try: torch._utils._rebuild_tensor_v2 except AttributeError: def _rebuild_tensor_ ...
- JS-斜杠和反斜杠的转换
例子:var url = "http://localhost:64177/Home/AccordionIndex"; 将斜杠转换成反斜杠: url = url .replace(& ...