一.自动化框架

可以理解为工具的集合,把日常所需要实现功能的代码,模块进行封装起来结合其他的工具进行测试。得出结论报告。

二.做自动框架步骤:

1.读取excel 获取用例,

2.解析用例

3.解析返回结果进行对比,检查是否通过还是失败

4.把返回的结果写入excel

5.生成报告,发邮件

三.搭建自动化框架

框架目录结构:

excel用例表格:

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 #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_countcontent = 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 = 0results = [] 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()

用例读取,判断请求方式

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) #[[url,get,data,check],[url,get,data,check]]return all_casedef 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']

文件配置

import requests
import nnlog from conf.setting
import LOG_PATH
import os
BAE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #atp的目录LOG_PATH = os.path.join(BAE_PATH,'logs') #log目录
CASE_PATH = os.path.join(BAE_PATH,'cases') #case目录
REPORT_PATH = os.path.join(BAE_PATH,'report') #report目录
CORE_PATH = os.path.join(BAE_PATH,'core') #core目录
MAIL_INFO = { 'user':'xxxx@qq.com', 'password':'sdfsdf', 'host':'smtp.qq.com', 'smtp_ssl':True,#发件箱是qq邮箱的话,改成True
}TO = ['511402865@qq.com','496647026@qq.com','649623416@qq.com','ray-zuo@qq.com']

URL获取参数进行解析

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 = urlself.data = dataself.headers = headersself.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代表返回的jsonexcept Exception as e:res = {"staus":2,"data":req.text} #2代表返回不是jsonlog_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代表返回的jsonexcept Exception as e:res = {"staus":2,"data":req.text} #2代表返回不是jsonlog_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)</pre>

解析请求数据

import random import string
import time
class ParseParam: #这个类是用来解析请求参数的func_map = ['phone','email','id_card','cur_time','money'] #映射函数的def __init__(self,param):self.param = paramself.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 resdef 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 410881199011212121def cur_time(self):return int(time.time())def order_id(self):#从数据库里面获取passdef session_id(self):#从redis里面获取的passdef money(self):return 10000 '''def parse(self): for func in self.func_map:temp = str(getattr(self,func)()) #手机号self.param = self.param.replace('<%s>'%func,temp)def strToDict(self): #这个函数是把请求参数转成字典的data ={}pl = self.param.split(',') for p in pl:temp = p.split('=') if len(temp)>1:key,value = tempdata[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)data = p.strToDict() print(data) '''print(p.phone())# res = getattr(p,'money') #获取一个对象里面的属性(方法、变量)# # print(res())# import os,requests# res = hasattr(requests,'get')#判断某个模块、类下面有没有某个方法或者变量# print(res)
用例的支持参数化,支持以下参数化:
<phone>   自动产生手机号
<id_card>  身份证号
<email>    邮箱
<cur_time>  当前时间戳 '''

校验检查点

import jsonpath
class ResponseParse:seqs = ['!=', '>=', '<=', '=', '<', '>', 'in', 'notin'] #定义支持的运算符def __init__(self,response,check):self.response = responseself.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) breakreturn format_list #1.检查点解析完成def get_real_value(self,key): #从字典里面获取key对应的valueres = jsonpath.jsonpath(self.response,'$..%s'%key) #$..%s这个是jsonpath这个模块的用法if res: return res[0] return '找不到该key【%s】'%key #2.取得实际的值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,msgdef 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()all_msg=''for check in check_list:#循环所有的检查点key,seq,hope = checkreal = self.get_real_value(key)status,msg = self.operation_check(real,seq,hope)all_msg = all_msg+msg+'\n' #累加提示信息if status: passelse: return '失败',all_msg return '通过',all_msg</pre>

产生excel文件写入校验结果

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/测试用例.xlsabs_path = os.path.join(setting.REPORT_PATH,today) #拼成当天的绝对路径if os.path.exists(abs_path): passelse:os.mkdir(abs_path) return abs_pathdef 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 = ressheet.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] #只获取到filenamecur_time = datetime.datetime.today().strftime('%H%M%S') #获取到当天时分秒new_file_name = cur_time+'_'+file_name #165530_测试用例.xlsreal_path = os.path.join(cur_date_dir,new_file_name)#拼路径new_book.save(real_path) return real_pathdef 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)


最后:如果对软件测试、接口测试、自动化测试、技术同行、持续集成、面试经验交流。感兴趣可以进到 902061117,群内会有不定期的分享测试资料。

如果文章对你有帮助,麻烦伸出发财小手点个赞,感谢您的支持,你的点赞是我持续更新的动力。

好文推荐

2021软件测试工程师面试题汇总(内含答案)-看完BATJ面试官对你竖起大拇指!

什么样的人适合从事软件测试工作?

软件测试和软件开发哪个发展更好

那个准点下班的人,比我先升职了…

搭一个简单的接口测试框架相关推荐

  1. 搭建一个简单springboot后端框架

    前言 框架知识是每个程序员都应该或多或少都要有所了解,作为后端开发更是以后进阶架构师必备的知识储备:以此为出发点,我们可以从搭建一个简单的后端框架开始,了解相关的技术点和搭建思路. 我们可以从创建项目 ...

  2. 如何搭建python框架_从零开始:写一个简单的Python框架

    原标题:从零开始:写一个简单的Python框架 Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. 你为什么想搭建一个Web框架?我想有下面几个原因: 有一个 ...

  3. 快速搭建一个简单的SSM框架

    1.准备工作 mysql数据库 idea工具 说明:本次是搭建一个SSM框架,首先要确保电脑配置好1.8以上的JDK(因为1.8以下的jdk某些东西不支持),mysql数据库直接使用不方便可以安装一个 ...

  4. 网络爬虫笔记 :一个简单的爬虫框架

    学了两节课的 Python 爬虫,也算是入门了吧.敲了两天的案例代码之后,我突然发现,这些代码虽然功能不同,写法各异,但是终归是有章可循的,整体框架是一致的.所以我自己整理了一个简单的爬虫框架,适合初 ...

  5. 一个简单的游戏框架:配置表方案

    一个简单的游戏框架:配置表方案 代码:https://github.com/HushengStudent/myGameFramework 1.配置表格式 csv,逗号分隔,可以使用wps和Excel打 ...

  6. 在Java中搭建一个简单的MVC框架

    搭建一个简单的Java MVC框架 一 . 前言 二. 代码实现 1. 思路分析 2. 代码实现 2.1 Controller注解 2.2 RequestMapping注解 2.3 UserContr ...

  7. 从零构建一个简单的 Python 框架

    为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点: 你有一个新奇的想法,觉得将会取代其他的框架 你想要获得一些名气 你遇到的问题很独特,以至于现有的框架不太合适 你对 web 框架是如何 ...

  8. 自己动手写一个简单的MVC框架(第一版)

    一.MVC概念回顾 路由(Route).控制器(Controller).行为(Action).模型(Model).视图(View) 用一句简单地话来描述以上关键点: 路由(Route)就相当于一个公司 ...

  9. python框架实例,从零构建一个简单的 Python 框架

    为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点: 你有一个新奇的想法,觉得将会取代其他的框架 你想要获得一些名气 你遇到的问题很独特,以至于现有的框架不太合适 你对 web 框架是如何 ...

最新文章

  1. java 设计一个geometricobject类,geometricobject类
  2. TCP长连接与短链接
  3. sql server xp_readerrorlog SQL语句查看错误日志
  4. linux下fdisk分区工具的使用
  5. 【Python Django2.0入门教程】ORM之QuerySet 数据查询API:all get filter distinct first last count
  6. 计算机里FC方式,【计算机基础】在0和1的世界里来来回回
  7. 机器学习中的范数规则化之(二)核范数与规则项参数选择以及RPCA
  8. 将字符串编码成 GBK
  9. 一文搞懂IT基础知识,讲通HTTP、TCP、IP、以太网
  10. 用计算机解决问题听课笔记,《计算机解决问题的过程》的教学设计
  11. dense sift matlab,一个 Dense SIFT 算法的 matlab 实现 | 学步园
  12. 2013年第一季度中国移动互联网应用安全检测与分析报告
  13. 【java学习之路】(java SE篇)007.常用类
  14. [剑指offer] 7. 斐波那契数列 (递归 时间复杂度)
  15. 如果粒子运动只受力影响,那么意识从何而来
  16. 正确的Kado ED「永遠のこたえ」
  17. visio反向生成mysql数据库模型图_Visio2010中逆向工程建立数据库模型图
  18. 易语言linux静态编译失败,易语言静态编译连接失败
  19. 【数学建模】2 TOPSIS优劣解距离法
  20. ISSCC2021 基于SRAM的存内计算16.3阅读记录

热门文章

  1. android 性能优化---(5)Bitmap图片资源优化
  2. 【欧洲已死】李开复:欧洲人工智能毫无希望
  3. python中通过pip安装套件
  4. iPhone 14仅两款Pro版搭载A16芯片 另外两款继续使用A15
  5. 史无前例!iPhone 14 Pro曝光:首次8GB RAM
  6. 自如CEO熊林接任董事长
  7. iQOO 8系列即将登场:首发三星E5 AMOLED全面屏
  8. 我爱我家:旗下APP已全面兼容鸿蒙系统
  9. 外媒:全球芯片短缺已影响洗衣机和烤面包机等小家电生产
  10. 英特尔第11代台式机处理器发布:或将是14nm最后的倔强