接口自动化测试实战教程

实现思路

使用excel管理用例用例信息,requests模块发送http请求,实现了记录日志,邮件发送测试报告的功能

目录结构如下:

下面直接上代码:

统筹脚本

# -*- coding:utf-8 -*-import osfrom interface import Interfacefrom testcase_get import Get_testcasefrom result_save import Save_test_resultfrom result_send import Send_reportfrom config.config import Configfrom logging_save import loggerif __name__ == "__main__":cur_path = os.path.split(os.path.realpath(__file__))[0]  # 获取当前文件绝对路径case_path = os.path.join(cur_path, "test_case", "20170602.xls")test_case = Get_testcase(case_path).readExcel()  # 获取用例if not isinstance(test_case, list):  # 判断用例是否获取成功logger.info("Test_case get failed... \n Done!")else:logger.info("获取用例成功")# 调用接口test_result = Interface().interfaceTest(test_case)# 获取执行结果,用于发邮件count_success = test_result[3]count_failure = test_result[4]failed_case_detail = test_result[5]# 保存测试结果Save_test_result().save_result(case_path, test_result[0], test_result[1], test_result[2])logger.info("保存测试结果成功")# 获取邮件配置信息mail_config = Config(os.path.join(cur_path, "config", "mail.conf")).get_mail_config()logger.info("获取邮箱配置成功")login_user = mail_config[0]login_pwd = mail_config[1]from_addr = mail_config[2]to_addrs = mail_config[3]smtp_server = mail_config[4]mail_send = Send_report(count_success, count_failure, failed_case_detail)# 获取最新测试报告last_report = mail_send.newest_report()logger.info("邮件发送结果")mail_send.send_result(login_user, login_pwd,from_addr, to_addrs,smtp_server,last_report)logger.info("DONE!")

请求封装

# coding:utf-8import jsonimport requestsfrom logging_save import loggerfrom result_check import Result_checkfrom 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-8import loggingimport sysimport tracebackimport 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-8class 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-8from xlutils import copyimport xlrdimport timeimport 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-8import smtplibfrom email.mime.text import MIMETextfrom email.header import Headerfrom email.mime.multipart import MIMEMultipartimport osfrom 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-8import 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-8class 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-8import 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.comlogin_pwd = ******from_addr =  BI<18******@163.com>to_addrs = ['18******@163.com']#to_addrs = ['1******@qq.com','******.com']smtp_server = smtp.163.comport = 25

测试报告

邮件接收结果

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!凡事要趁早,特别是技术行业,一定要提升技术功底。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/230494.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Termux安装MySQL数据库并通过内网穿透实现公网远程访问

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

【MongoDB】--MongoDB的Sort排序问题

目录 一、问题背景描述1.1、问题背景1.2、问题分析 二、建立索引支持深度翻页查询2.1、调整sort排序的内存限制【不建议】2.2、创建索引2.3、拓展--组合索引什么时候失效 二、聚合查询解决深度翻页查询 一、问题背景描述 1.1、问题背景 现实系统页面翻页到20000页之后&#x…

Improving IP Geolocation with Target-Centric IP Graph (Student Abstract)

ABSTRACT 准确的IP地理定位对于位置感知的应用程序是必不可少的。虽然基于以路由器为中心(router-centric )的IP图的最新进展被认为是前沿的,但一个挑战仍然存在:稀疏IP图的流行(14.24%,少于10个节点,9.73%孤立)限制了图的学习。为了缓解这个问题,我们将目标主机(ta…

【LeetCode刷题笔记(8-2)】【Python】【接雨水】【单调栈】【困难】

文章目录 引言接雨水题目描述提示 解决方案2&#xff1a;【单调栈】结束语 【接雨水】 【LeetCode刷题笔记&#xff08;8-1&#xff09;】【Python】【接雨水】【动态规划】【困难】 引言 编写通过所有测试案例的代码并不简单&#xff0c;通常需要深思熟虑和理性分析。虽然这…

200kw直流电子负载测试

在进行200kw直流电子负载测试时&#xff0c;需要设置合适的负载参数&#xff0c;如电流、电压和功率等&#xff0c;并记录测试结果。在测试过程中&#xff0c;可以通过改变负载参数来模拟不同工作条件下的电子设备的性能。通过对电子设备在不同负载条件下的响应进行测试和分析&…

JupyterHub 如何切换 conda 小环境

JupyterHub 如何切换 conda 小环境 服务器已经部署好 JupyterHub &#xff0c;相关端口请看对应答疑群群公告。在Jupyterhub 中使用 conda 创建的小环境&#xff0c;首先 ssh 登录上服务器或者在 JupyterHub 网页端打开终端 terminal。然后安装 conda &#xff0c;方法请见 Q4&…

【MyBatis Plus】逻辑删除、分页、乐观锁的应用及讲解

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《MyBatis-Plus》。&#x1f3af;&#x1f3af; &am…

改进灰狼算法求解:考虑需求响应的风-光柴-储容量优化配置

目录 文章摘要&#xff1a; 亮点&#xff1a; 研究背景&#xff1a; 考虑需求相应的容量配置&#xff1a; 风、光、柴、储微电网模型&#xff1a; 储能配置模型&#xff1a; 改进的灰狼算法&#xff1a; 基于余弦规律变化的收敛因子 引入动态权重策略 运行效果&#…

数据结构:图文详解 队列 | 循环队列 的各种操作(出队,入队,获取队列元素,判断队列状态)

目录 队列的概念 队列的数据结构 队列的实现 入队 出队 获取队头元素 获取队列长度 循环队列的概念 循环队列的数据结构 循环队列的实现 判断队列是否为空 判断队列是否已满 入队 出队 得到队头元素 得到队尾元素 队列的概念 队列&#xff08;Queue&#xff0…

基于单片机的视力保护及身姿矫正器设计(论文+源码)

1. 系统设计 在本次设计中&#xff0c;其系统整个框图如图2-1所示。其主要的核心控制模块由超声波模块&#xff0c;光敏电阻&#xff0c;按键模块&#xff0c;复位电路&#xff0c;红外模块&#xff0c;LCD显示等组成。其包括自动模式&#xff0c;手动模式。自动模式&#xff…

upload-labs笔记

简介 upload-labs是一个使用php语言编写的&#xff0c;专门收集渗透测试和CTF中遇到的各种上传漏洞的靶场。旨在帮助大家对上传漏洞有一个全面的了解。目前一共21关&#xff0c;每一关都包含着不同上传方式。 文件上传漏洞是指&#xff1a; Web 服务器允许用户将文件上传至其…

Linux部署Nacos注册中心结合内网穿透实现远程访问UI管理界面

文章目录 1. Docker 运行Nacos2. 本地访问Nacos3. Linux安装Cpolar4. 配置Nacos UI界面公网地址5. 远程访问 Nacos UI界面6. 固定Nacos UI界面公网地址7. 固定地址访问Plik8. 结语 Nacos是阿里开放的一款中间件,也是一款服务注册中心&#xff0c;它主要提供三种功能&#xff1a…

多序列图像拼接

这里写自定义目录标题 图像匹配图像匹配代码 图像融合main.py运行代码 总的来说&#xff0c;步骤如下&#xff1a; 效果如下&#xff1a; 拼接好的图如下&#xff1a; 图像匹配 依次为 特征点提取&#xff0c;特征点筛选&#xff0c;图像变换。 常见的图像匹配算法有&…

2024上半年软考别轻易尝试!先了未发布

最近几年&#xff0c;软件考试变得非常受欢迎&#xff01;不论你的专业、学历或工作时间如何&#xff0c;你都可以报名参加&#xff0c;而且通过考试取得证书还能用来抵扣个人所得税、评职称、帮助落户和参与招投标等等。 身边的朋友们纷纷参加软考&#xff0c;这让我也产生了…

下一代实时数据库:Apache Doris 【六】数据划分

3.4 数据划分 3.4.1 列定义3.4.2 分区与分桶3.4.3 PROPERTIES3.4.4 ENGINE3.4.5 其他后记 3.4 数据划分 以 3.3.2 的建表示例来理解。 3.4.1 列定义 以 AGGREGATE KEY 数据模型为例进行说明。更多数据模型参阅 Doris 数据模型。 列的基本类型&#xff0c; 可以通过在 mysql-cli…

山区老人爱的礼物丨走进武隆区土地乡为山区老人送温暖

从车水马龙的城市到人烟稀少的乡村&#xff0c;穿越重峦叠嶂的高山&#xff0c;见到的是独属于大山的辽阔和山区老人眼中的星河。近日&#xff0c;传益千里为爱出发&#xff0c;在三棵柚公益基金会的支持下开展“山区老人爱的礼物”公益计划&#xff0c;走进武隆区土地乡&#…

Unity Meta Quest 一体机开发(十一):【手势追踪】远距离抓取

文章目录 &#x1f4d5;教程说明&#x1f4d5;玩家配置 DistanceHandGrabInteractor&#x1f4d5;物体配置 DistanceHandGrabInteractable&#x1f4d5;调整物体飞向手部的速度&#x1f4d5;调整探测物体的范围⭐HandFrustumNarraw⭐HandFrustumWide⭐HeadFrustum 此教程相关的…

探讨前端技术的未来:创新与适应的必要性

一、引言 2023年&#xff0c;IT圈似乎被一种悲观的论调所笼罩&#xff0c;那就是“Java 已死、前端已凉”。然而&#xff0c;真相是否如此呢&#xff1f;本文将围绕这一主题&#xff0c;探讨前端的现状和未来发展趋势。 二、为什么会出现“前端已死”的言论 这一言论的出现并…

盛元广通农产品质量检测实验室管理系统

盛元广通农产品质量检测实验室管理系统旨在打造智慧化市、区/镇、企业三位一体的区域安全监管体系&#xff0c;系统可以记录和追踪样品的来源、处理过程和结果&#xff0c;确保样品的安全性和可追溯性自动化检测流程&#xff0c;包括检测方法的设定、数据的记录和分析等&#x…

健康卤味思想引领市场新潮流,卤味市场迎来健康变革

健康卤味思想正在逐渐渗透到卤味市场中&#xff0c;引领着消费者对于卤味产品的选择和需求。这一变革不仅为消费者带来了更加健康、美味的卤味产品&#xff0c;也为卤味市场注入了新的活力。 一、健康卤味思想的兴起 随着消费者对于健康饮食的关注度不断提高&#xff0c;健康卤…