接口自动化测试实战

实现思路

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

目录结构如下:

同时,我也准备了一份软件测试视频教程(含接口、自动化、性能等),需要的可以直接在下方观看,或者直接关注VX公众号:互联网杂货铺,免费领取

软件测试视频教程观看处:

华测教育软件测试进阶全套视频教程(2023全网最新版,软件测试进阶自学必备)

下面直接上代码:

统筹脚本

# -*- 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

测试报告

邮件接收结果

写在最后

PS:这里分享一套软件测试的自学教程合集。对于在测试行业发展的小伙伴们来说应该会很有帮助。除了基础入门的资源,博主也收集不少进阶自动化的资源,从理论到实战,知行合一才能真正的掌握。全套内容已经打包到网盘,内容总量接近500个G。如需要软件测试学习资料,关注公众号(互联网杂货铺),后台回复1,整理不易,给个关注点个赞吧,谢谢各位大佬!

☑ 240集-零基础到精通全套视频课程
☑ [课件+源码]-完整配套的教程
☑ 18套-测试实战项目源码
☑ 37套-测试工具软件包
☑ 268道-真实面试题
☑ 200个模板-面试简历模板、测试方案模板、软件测试报告模板、测试分析模版、测试计划模板、性能测试报告、性能测试报告、性能测试脚本用例模板(信息完整)

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

 

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

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

相关文章

MySQL 连接出现 Authentication plugin ‘caching_sha2_password的处理方法(使用第二种)

出现这个原因是mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password, 解决问题方法有两种,一种是升级navicat驱动,一种是把mysql用户登录密码加密规则还原成mysql_native_password. 1. 升级MySQL版本 较早的MySQL版本可能不…

TSINGSEE青犀老旧小区升级改造AI+视频监控方案

一、背景与需求 近年来&#xff0c;政府高度重视城镇老旧小区改造工作&#xff0c;强调要加快老旧小区改造&#xff0c;不断完善城市管理和服务&#xff0c;彻底改变粗放型管理方式&#xff0c;让人民群众在城市生活得更方便、更舒心、更美好。老旧小区升级改造面临以下问题&a…

Kotlin中使用ViewBinding绑定控件并添加点击事件

文章目录 效果1、加入依赖2、与控件进行绑定在 Activity 中使用视图绑定 3、监听控件 效果 实现源码 class MainActivity : AppCompatActivity() {lateinit var binding:ActivityMainBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstan…

计算机毕业设计 基于SpringBoot大学生创新创业项目管理系统的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

【安装tensorflow-CPU版本】

一、安装目的二、安装过程三、总结 一、安装目的 使自己的jupyter能用tensorflow 二、安装过程 首先打开anaconda prompt 接着输入conda list 查看自己是否安装了tensorflow 在 Python 中使用 pip 工具来升级 pip 自身并指定了使用清华大学的镜像源进行安装 python -m pip …

DoLa:对比层解码提高大型语言模型的事实性

DoLa&#xff1a;对比层解码提高大型语言模型的事实性 摘要1 引言2 方法2.1 事实知识在不同层级上演化2.2 动态早期层选择2.3 预测对比 3 实验3.1 任务3.2 实验设置3.3 多项选择3.3.1 TruthfulQA&#xff1a;多项选择3.3.2 FACTOR&#xff1a;维基、新闻 3.4 开放式文本生成3.4…

开始学习Go编程

探索Go编程中的语法、数据类型和控制流 Go&#xff0c;又称为Golang&#xff0c;因其简单性、性能和效率而广受欢迎。在本文中&#xff0c;我们将深入研究构成Go编程语言基础的基本概念。从理解其语法和数据类型到掌握控制流和函数&#xff0c;我们将为您提供启动Go编程之旅所…

利用JMeter生成加密数据写入数据库

有部分数据直接插入数据库是不可以的&#xff0c;需要加密处理&#xff0c;例如密码都指定为加密后的数据字符串。今天我们来学习一下如何利用JMeter生成加密数据并写入MySQL数据库中。如何JMeter如何连接数据库&#xff0c;可以看我之前写的随笔&#xff0c;JMeter接口测试-JD…

Linux之线程池

线程池 线程池概念线程池的应用场景线程池实现原理单例模式下线程池实现STL、智能指针和线程安全其他常见的各种锁 线程池概念 线程池&#xff1a;一种线程使用模式。 线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待…

基于机器视觉的手势检测和识别算法 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的手势检测与识别算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng…

【代码随想录】算法训练计划03

1、203. 移除链表元素 题目&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 思路&#xf…

linux进程间通信

文章目录 前言一、管道通信1、进程间通信目的2、进程间通信分类3、匿名管道通信3.1 匿名管道通信介绍3.2 匿名管道通信3.3 匿名管道读写规则3.4 匿名管道特点3.5 站在文件描述符角度-深度理解管道3.6 站在内核角度-管道本质 4、进程池练习5、命名管道6、匿名管道与命名管道的区…

智慧公厕:细致入微的城市贴心服务与便捷方便的生活配套

在现代城市生活中&#xff0c;公厕作为重要的城市基础设施&#xff0c;一直是城市发展的关键环节之一。然而&#xff0c;传统的公厕常常存在着设施陈旧、管理不善和卫生状况差等问题&#xff0c;给市民的生活品质和城市形象带来了一定的影响。为了提供更好的城市公厕服务&#…

Python 框架学习 Django篇 (六) 数据表关联、ORM关联

在后端服务器开发中&#xff0c;特别是前后端分离的架构中数据库是非常重要的&#xff0c;后端主要就是负责管理数据&#xff0c;而我们经常使用的mysql、oracle 都是关系型数据库&#xff0c;什么是关系型数据库&#xff1f;就是建立在关系模型基础上的数据库&#xff0c;而最…

Sql Server中的表组织和索引组织(聚集索引结构,非聚集索引结构,堆结构)

正文 SqlServer用三种方法来组织其分区中的数据或索引页&#xff1a; 1、聚集索引结构 聚集索引是按B树结构进行组织的&#xff0c;B树中的每一页称为一个索引节点。每个索引行包含一个键值和一个指针。指针指向B树上的某一中间级页&#xff08;比如根节点指向中间级节点中的…

超全面测评!2023年最常用的15款原型设计工具

在互联网和软件行业中&#xff0c;原型设计是产品经理、交互设计师以及运营人员等职位必不可少的一门技能。原型设计工具的重要性也是人尽皆知&#xff0c;这都是因为原型设计工具是帮助设计者表达产品想法、功能设定及流程逻辑的最佳方式。 今天就为大家带来原型设计工具的相…

「林曦的亲子美育」讲讲关于阅读的那些事儿

「林曦的亲子美育」是“林曦的小世界”2023年策划的一档新栏目。林曦老师作为一个“小男生的妈妈”,在这些年分享了许多关于亲子教育的心得&#xff1a;以“美”作为连接和最高标准&#xff0c;会护持着小朋友的选择和人生。教育是一个生活的过程。做一餐饭、读一本书、看一张画…

HCL模拟器选路实验案例

此选路题目选自职业院校技能竞赛中的一道题比较考验思路&#xff0c;适合于参加新华三杯大赛以及网络专业的同学&#xff0c;当做练习题目进行解题​​​​​​​ 题目 1.S1、S2、R1、R2运行ospf进程100&#xff0c;区域0&#xff0c;R1、R2、R3、R4、R5运行ospf进程200&#…

Ocelot简易教程目录

Ocelot简易教程目录 这里写目录标题 Ocelot简易教程目录 Ocelot简易教程&#xff08;一&#xff09;之Ocelot是什么Ocelot简易教程&#xff08;二&#xff09;之快速开始1Ocelot简易教程&#xff08;二&#xff09;之快速开始2Ocelot简易教程&#xff08;三&#xff09;之主要特…

安装虚拟机找不到虚拟网啦1(eth1)不出现

一、安装虚拟机找不到虚拟网啦1&#xff08;eth1&#xff09;不出现 1、先安装virtualbox 2、再安装vagrant 3、在windows使用ipconfig没有VirtualBoxHost-OnlyNetWork解决方法 1) 解决办法 在windows的设置中找到 网络和Internet 选项&#xff0c;选择右侧 更改适配器选项 …