广州网站建设培训班/海外营销
目录
实现思路
统筹脚本
请求封装
日志封装
结果比对
结果邮件
用例获取及数据格式化
请求url转换
测试用例excel结构
测试报告
邮件接收结果
资料获取方法
实现思路
使用excel管理用例用例信息,requests模块发送http请求,实现了记录日志,邮件发送测试报告的功能
目录结构如下:
下面直接上代码:
统筹脚本
请求封装
# coding:utf-8
import json
import requestsfrom logging_save import logger
from result_check import Result_check
from url_transform import urltransformclass Interface:def __init__(self, ):passdef interfaceTest(self, case_list):"""接口调用主函数"""# 用于存结果res_flags = []# 用于存请求报文request_urls = []# 用于存返回报文responses = []# 用户存失败的用例failed_case = []# 统计成功失败的用例数count_success = 0count_failure = 0for case in case_list:try:# 模块product = case[0]# 用例idcase_id = case[1]# 用例标题interface_name = case[2].strip('\n')# 用例描述case_detail = case[3]# 请求方式method = case[4]# 请求urlurl = case[5]# 入参param = case[6]# 预期结果res_check = case[7]except Exception as e:return '测试用例格式不正确!%s' % e# 定义消息头信息headers = {'content-type': 'application/json','User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}# 对url进行封装new_url = urltransform().urltransform(url, method, param)if method.upper() == 'GET':results = requests.get(new_url).textlogger.info(u'正在调用接口: %s' % interface_name)# print resultsresponses.append(results)# 用于存储预期结果与实际结果的比较结果res = Result_check().interface_result_check(results, res_check)request_urls.append(new_url)else:request_urls.append(new_url)if param == '':passelse:data = json.loads(param) # 将参数转化为json格式results = requests.post(new_url, data=json.dumps(data), headers=headers).textresponses.append(results)res = Result_check().interface_result_check(results, res_check)if 'pass' in res:res_flags.append('pass')count_success += 1else:logger.warning(u'接口返回结果与预期结果不一致!失败URL: %s METHOD :%s' % (url, method))res_flags.append('fail')count_failure += 1failed_case.append((interface_name, method, url))logger.info(u'共执行 %s 条用例,PASS: %s,FAILED: %s' % (len(case_list), count_success, count_failure))return res_flags, request_urls, responses, count_success, count_failure, failed_case
日志封装
# coding=utf-8
import logging
import sys
import traceback
import timeclass LoggingUtils:'''===========封装日志工具类的基本操作============='''def __init__(self,logfile):''':param logfile:'''self.logger = logging.getLogger(logfile)self.hdlr = logging.FileHandler(logfile)formatter = logging.Formatter('%(asctime)s %(levelname)s - %(message)s')self.ch = logging.StreamHandler()self.ch.setLevel(logging.INFO)self.ch.setFormatter(formatter)self.hdlr.setFormatter(formatter)self.logger.addHandler(self.hdlr)self.logger.addHandler(self.ch)self.logger.setLevel(logging.DEBUG)def debug(self, msg):''':param msg::return:'''self.logger.debug(msg)self.hdlr.flush()def info(self, msg):''':param msg::return:'''self.logger.info(msg)self.hdlr.flush()def warning(self,msg):self.logger.warning(msg)self.hdlr.flush()def error(self, msg):''':param msg::return:'''self.logger.error(msg)# self.logger.removeHandler(logging.StreamHandler())self.logger.removeHandler(self.ch)self.hdlr.flush()def error_sys(self, limit=None):''':param limit::return:'''exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()if limit is None:if hasattr(sys, 'tracebacklimit'):limit = sys.tracebacklimitn = 0eline = '\n'while exceptionTraceback is not None and (limit is None or n < limit):f = exceptionTraceback.tb_framelineno = exceptionTraceback.tb_linenoco = f.f_codefilename = co.co_filenamename = co.co_nameeline += ' File "%s", line %d, in %s \n ' % (filename, lineno, name)exceptionTraceback = exceptionTraceback.tb_nextn = n + 1eline += "\n".join(traceback.format_exception_only(exceptionType, exceptionValue))self.logger.error(eline)self.hdlr.flush()
timer = time.strftime('%Y-%m-%d',time.localtime())
logger = LoggingUtils('%s.log'%timer)
结果比对
#coding:utf-8
class result_check():def __init__(self):passdef result_check(self,results,res_check):'''结果对比函数'''#返回结果,将结果中的json数据转化为可以和预期结果比较的数据res = results.replace('":"','=').replace('" : "','=')#预期结果,是xx=11;xx=22res_check = res_check.split(';')for s in res_check:if s in res:passelse:return '结果不匹配 '+ str(s)return 'pass'result_save.py 保存测试结果的模块,复制原有的用例,保存为新的excel
#coding:utf-8
from xlutils import copy
import xlrd
import time
import osclass Save_test_result():def __init__(self):passdef save_result(self,file_path,res_flags,request_urls,responses):''':return:'''book = xlrd.open_workbook(file_path)new_book = copy.copy(book)sheet = new_book.get_sheet(0)i = 1for request_url, response, flag in zip(request_urls, responses, res_flags):sheet.write(i, 8, u'%s' % request_url)sheet.write(i, 9, u'%s' % response)sheet.write(i, 10, u'%s' % flag)i += 1report_path = os.path.abspath(os.path.join('report'))if not os.path.exists(report_path):os.makedirs(report_path)new_book.save(os.path.abspath(os.path.join(report_path, 'Report@%s.xls' % time.strftime('%Y.%m.%d@%H%M%S'))))
结果邮件
#coding:utf-8
import smtplib
from email.mime.text import MIMEText
from email.header import Header
from email.mime.multipart import MIMEMultipart
import os
from logging_save import loggerclass Send_report(object):def __init__(self,count_success,count_failure,failed_case):''':param count_success::param count_failure::param failed_case:'''self.count_success = count_successself.count_failure = count_failureself.failed_case = failed_casedef newest_report(self,testreport='report'):'''获取最新的测试报告:param testreport::return:'''lists = os.listdir(testreport)lists.sort(key=lambda fn: os.path.getmtime(os.path.join(testreport,fn)))file_new = os.path.join(testreport, lists[-1])logger.info('获取最新附件报告成功')return file_newdef send_result(self,username,passwd,from_addr,to_addrs,smtpserver,*args):''':param username::param passwd::param from_addr::param to_addrs::param smtpserver::param args::return:'''sender = from_addrsubject = '财富港接口测试结果'username = usernamepasswd = passwd'''邮件内容'''tille = (u'用例名称', u'请求方式', u'url')details = (u'成功: ' + str(self.count_success) + u'失败: ' + str(self.count_failure)) + '\n' + u'失败的用例如下 :' + \'\n' + '\n'.join(str(zip(tille, i)) for i in self.failed_case).decode('unicode-escape')logger.info('邮件附件为: %s' %(args[0].split('\\')[1]))if args != None: #判断是否添加附件msg = MIMEMultipart()msg.attach(MIMEText(details, 'plain', 'utf-8'))i = 0while i < len(args): #可以添加多个附件part = MIMEText(open(args[i], 'rb').read(), 'base64', 'utf-8')part["Content-Type"] = 'application/octet-stream'part["Content-Disposition"] = 'attachment; filename="%s"'%args[i]msg.attach(part) #添加附件i += 1msg['subject'] = Header(subject, 'utf-8')msg['From'] = from_addrmsg['To'] = ','.join(eval(to_addrs)) #兼容多个收件人smtp = smtplib.SMTP()try:smtp.connect(smtpserver)smtp.login(username, passwd)smtp.sendmail(sender, eval(to_addrs), msg.as_string())smtp.close()logger.info('带附件测试报告发送成功!')except smtplib.SMTPAuthenticationError,e:logger.error('邮箱账户或密码错误: '+ str(e))else:msg = MIMEText(details, 'plain', 'utf-8')msg['subject'] = Header(subject, 'utf-8')msg['From'] = from_addrmsg['To'] = ','.join(eval(to_addrs))smtp = smtplib.SMTP()try:smtp.connect(smtpserver)smtp.login(username, passwd)smtp.sendmail(sender, eval(to_addrs), msg.as_string())logger.info('测试报告发送成功!')smtp.close()except smtplib.SMTPAuthenticationError,e:logger.error('邮箱账户或密码错误 : '+str(e))
用例获取及数据格式化
#coding:utf-8
import xlrdfrom logging_save import loggerclass Get_testcase(object):def __init__(self, file_path):''':param file_path: 用例文件路径'''self.file_path = file_pathdef readExcel(self):'''读取用例函数:return: 测试用例列表'''try:book = xlrd.open_workbook(self.file_path) # 打开excelexcept Exception, error:logger.error('路径不在或者excel不正确 : ' + str(error))return errorelse:sheet = book.sheet_by_index(0) # 取第一个sheet页rows = sheet.nrows # 取这个sheet页的所有行数case_list = [] # 用于保存用例信息for i in range(rows):if i != 0:case_list.append(sheet.row_values(i)) # 把每一条测试用例添加到case_list中return case_list
请求url转换
#coding:utf-8
class urltransform(object):def __init__(self):passdef urltransform(self, url, method, param):''':return:'''if param == '':new_url = urlelse:if method.upper() == 'GET':new_url = url + '?' + param.replace(';', '&') #如果有参数,且为GET方法则组装urlelse:new_url = urlreturn new_url
测试用例excel结构
config目录下,config.py 获取配置文件信息的模块
#conding:utf-8
import ConfigParserclass Config(object):def __init__(self,file_path):self.config = ConfigParser.ConfigParser()self.config.read(file_path)def get_mail_config(self):login_user = self.config.get('SMTP', 'login_user')login_pwd = self.config.get('SMTP', 'login_pwd')from_addr = self.config.get('SMTP', 'from_addr')to_addrs = self.config.get('SMTP', 'to_addrs')smtp_server = self.config.get('SMTP', 'smtp_server')port = self.config.get('SMTP', 'port')return login_user, login_pwd , from_addr, to_addrs,smtp_server, portdef report_save_config(self):pass
mail.conf
[SMTP]
login_user = 18******@163.com
login_pwd = ******
from_addr = BI<18******@163.com>
to_addrs = ['18******@163.com']
#to_addrs = ['1******@qq.com','******.com']
smtp_server = smtp.163.com
port = 25
测试报告
邮件接收结果
资料获取方法
【留言777】
各位想获取源码等教程资料的朋友请点赞 + 评论 + 收藏,三连!
三连之后我会在评论区挨个私信发给你们~
相关文章:

基于Python 简易实现接口测试自动化
目录 实现思路 统筹脚本 请求封装 日志封装 结果比对 结果邮件 用例获取及数据格式化 请求url转换 测试用例excel结构 测试报告 邮件接收结果 资料获取方法 实现思路 使用excel管理用例用例信息,requests模块发送http请求,实现了记录日志&…...

创建线程、线程的挂起与恢复、线程的优先级与终止线程
目录 一、创建线程 CreateThread函数: 下面是示例: 编辑 ThreadProc函数解释: DWORD的本质是 unsigned long PVOID的本质是 void* 二、线程的终止 1.WaitForSingleObject()函数: 示例如下: 2.ExitThread()函…...

[保研/考研机试] KY180 堆栈的使用 吉林大学复试上机题 C++实现
题目链接: 堆栈的使用_牛客题霸_牛客网 描述 堆栈是一种基本的数据结构。堆栈具有两种基本操作方式,push 和 pop。其中 push一个值会将其压入栈顶,而 pop 则会将栈顶的值弹出。现在我们就来验证一下堆栈的使用。 输入描述: 对于…...

【AI理论学习】手把手推导扩散模型:Diffusion Models(DDPM)
手把手推导扩散模型:Diffusion Models(DDPM) DDPM理论回顾前置知识过程详解Forward ProcessReverse Process DDPM算法伪代码训练部分采样部分 总结一下 参考链接 在这篇博客文章中,我们将深入研究 去噪扩散概率模型(也称为 DDPM&…...

智能汽车 论坛收集
1.焉知汽车 焉知汽车 2.智能汽车俱乐部 智能汽车资源网 - 智能表面,智能内饰,新能源汽车,HMI,人车交互,智能车灯,车用材料 3.行业报告 发现报告 - 专业研报平台丨收录海量行业报告、券商研报丨免费分享…...

24届近5年南京航空航天大学自动化考研院校分析
今天给大家带来的是南京航空航天大学控制考研分析 满满干货~还不快快点赞收藏 一、南京航空航天大学 学校简介 南京航空航天大学创建于1952年10月,是新中国自己创办的第一批航空高等院校之一。1978年被国务院确定为全国重点大学;1981年经…...

Linux Day07
一、僵死进程 1.1僵死进程产生的原因 子进程先于父进程结束, 而父进程没有获取子进程退出码,释放子进程占用的资源,此时子进程将成为一个僵死进程。 在第一个框这里时父进程子进程都没有结束,显示其pid 父进程是2349,子进程是235…...
数字化管理,让MRO工业品更高效
MRO商品数字化是将MRO商品的采购、库存及记录过程进行数字化管理,以提高MRO商品的效率和可控性。MRO(Maintenance, Repair and Operations)一般用于维修、保养及日常运营工作中,包括五金工具、紧固件、精加工刀具、备品备件、切屑…...

layui中渲染table表格
页面布局 可直接根据文档要求去写 table 组件(这个不重要) <table lay-filter"SyDictTable" id"SyDictTable" lay-data"{id: SyDictTable}"></table>Js 重要的是去修改JS里面的东西,比如&#…...

2023-08-10LeetCode每日一题(下降路径最小和 II)
2023-08-10每日一题 一、题目编号 1289. 下降路径最小和 II二、题目链接 点击跳转到题目位置 三、题目描述 给你一个 n x n 整数矩阵 grid ,请你返回 非零偏移下降路径 数字和的最小值。 非零偏移下降路径 定义为:从 grid 数组中的每一行选择一个数…...

网络基础2(HTTP,HTTPS,传输层协议详解)
再谈协议 在之前利用套接字进行通信的时候,我们都是利用 “字符串” 进行流式的发送接收,但是我们平常进行交流通信肯定不能只是简单的发送字符串。 比如我们用QQ进行聊天,我们不仅需要得到对方发送的消息,还要知道对方的昵称&…...

Java实现籍贯级联选择器
在工作中要求写一个籍贯的级联选择器,记录一下自己写这个级联选择器的过程,因为自己才刚开始工作,有很多地方都没有考虑的很清楚,希望各位大佬能给出建议。 一、需求 A:正常的23个省,籍贯由“省区/县/市”组成…...

每日一学——OSI参考模型
OSI参考模型(Open Systems Interconnection Reference Model)是国际标准化组织(ISO)制定的一个网络通信协议的概念框架。它将网络通信划分为七个层次,每个层次负责不同的功能和任务,从物理层到应用层依次为…...

虚幻5中Lumen提供哪些功能以及如何工作的
虚幻引擎 5 中的 Lumen 是一个完全动态的全局照明和反射系统。它可以在虚幻引擎 5 中使用,因此创作者无需自行设置。它是为下一代控制台和建筑可视化等高端可视化而设计的。那么它提供了哪些功能以及如何工作? 全局照明 当光离开光源时,它会…...

Linux C 语言 mosquitto 方式 MQTT 发布消息
1 说明 采用 mosquitto 库,实现对主题发布消息。 其中服务器有做限制,需要对应的 cilent id ,cafile 、certfile 、keyfile 等配置 2 开发环境 采用ubuntu 直接编译调试 安装mosquitto 库 sudo apt install libmosquitto-dev sudo apt-ge…...

利用NtDuplicateObject进行Dump
前言 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。(本文仅用于交流学习) 这是国外老哥2020年提出的一种蛮有意思的思路。 我们先来看看大致的思路是…...

【快应用】list组件如何区分滑动的方向?
【关键词】 list组件、滑动方向、scroll 【问题背景】 有cp反馈list这个组件在使用的时候,不知道如何区分它是上滑还是下滑。 【问题分析】 list组件除了通用事件之外,还提供了scroll、scrollbottom、scrolltop、scrollend、scrolltouchup事件&#x…...

【深入了解pytorch】PyTorch扩展:如何使用PyTorch的扩展功能
【深入了解pytorch】PyTorch扩展:如何使用PyTorch的扩展功能 PyTorch扩展:展示如何使用PyTorch的扩展功能1. 自定义损失函数2. 自定义数据加载器3. 自定义优化器总结PyTorch扩展:展示如何使用PyTorch的扩展功能 PyTorch作为一个开源的深度学习框架,在研究和应用领域广受欢…...

Vue3——如何实现页面访问拦截
在现代的Web开发中,页面访问拦截是一个非常常见的需求。通过拦截页面访问,我们可以控制用户在访问特定页面之前需要满足的条件,比如登录状态、权限等。Vue是一个非常流行的JavaScript框架,它提供了许多强大的工具和功能࿰…...

nginx配置gzip
在 Nginx 中启用 Gzip 压缩可以大幅减少传输内容的大小,从而加快网页加载速度。 打开 Nginx 的配置文件,通常是 /etc/nginx/nginx.conf 或者 /etc/nginx/conf.d/default.conf。找到 http 配置块,在其中添加以下代码来开启 Gzip 压缩ÿ…...

ExtJS教程_编程入门自学教程_菜鸟教程-免费教程分享
教程简介 Ext JS是一个流行的JavaScript框架,它为使用跨浏览器功能构建Web应用程序提供了丰富的UI。 Ext JS基本上用于创建桌面应用程序它支持所有现代浏览器,如IE6 ,FF,Chrome,safari 6 等。Ext JS基于MVC / MVVM架构…...

【el-upload】批量上传图片时在before-upload中添加弹窗判断时的踩坑记录
一、初始代码 1. 初始使用组件代码片段 <!-- 上传 --> <DialogUploadFile ref"uploadFile" success"refresh" />// 上传 const uploadHandle () > {if (selections.value.length ! 1) {onceMessage.warning(请选择一条数据操作)return}u…...

【Java基础】- JVM之Dump文件详解
Java基础 - JVM之Dump文件详解 文章目录 Java基础 - JVM之Dump文件详解一、什么是Dump三、为什么需要Dump分析思路 四、Dump记录哪些内容4.1 Java dump 文件的格式和内容段格式行格式 4.2 常用分类heap dump和thread dumpheap dumpthread dump 五、如何生产Dump文件5.1 获取hea…...

基于Vue+wangeditor实现富文本编辑
目录 前言分析实现具体解决的问题有具体代码实现如下效果图总结前言 一个网站需要富文本编辑器功能的原因有很多,以下是一些常见的原因: 方便用户编辑内容:富文本编辑器提供了类似于Office Word的编辑功能,使得那些不太懂HTML的用户也能够方便地编辑网站内容。提高用户体验…...

深入理解 Spring 中的 @RequestBody 和 @ResponseBody 注解及其区别
引言 在现代的 Web 开发中,处理 HTTP 请求和响应是不可或缺的任务。Spring Framework 提供了丰富的功能来简化这些任务,并使开发人员能够更专注于业务逻辑。在本文中,我们将深入探讨 Spring 中的 RequestBody 和 ResponseBody 注解࿰…...

【论文阅读】EULER:通过可扩展时间链接预测检测网络横向移动(NDSS-2022)
作者:乔治华盛顿大学-Isaiah J. King、H. Howie Huang 引用:King I J, Huang H H. Euler: Detecting Network Lateral Movement via Scalable Temporal Graph Link Prediction [C]. Proceedings 2022 Network and Distributed System Security Symposium…...

手动创建一个DOCKER镜像
1. 我们先使用C语言写一个hello-world程序 vim hello.c # include <stdio.h>int main() {print("hello docker\n"); } 2. 将hello.c文件编译成二进制文件, 需要安装工具 yum install gcc yum install glibc-static 开始编译 gcc -static hello.c -o hello 编译…...

SSM(Vue3+ElementPlus+Axios+SSM前后端分离)--搭建Vue 前端工程[一]
文章目录 SSM--搭建Vue 前端工程--项目基础界面实现功能01-搭建Vue 前端工程需求分析/图解代码实现搭建Vue 前端工程下载node.js LTS 并安装: node.js 的npm创建Vue 项目使用idea 打开ssm_vue 项目, 并配置项目启动 Vue3 项目目录结构梳理Vue3 项目结构介绍 配置Vue 服务端口El…...

Idea使用Docker插件实现maven打包自动构建镜像
Docker 开启TCP 服务 vi /lib/systemd/system/docker.service改写以下内容 ExecStart/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock重启服务 #重新加载配置文件 systemctl daemon-reload #重启服务 systemctl restart docker.service此时docker已…...

Tailwind css优于Bootstrap 7个原因
在某些情况下,Tailwind css 比 Bootstrap 更好,因为它是一个低级 CSS 框架,可让您根据需要构建自己的自定义组件。如果使用得当,它非常注重性能,可以显着减少 CSS 负载并确保更快的渲染。如果 Web 性能和自定义是您的首…...