【接口自动化】06-轻量级框架封装(完):日志监控、数据驱动及断言
一、前言上一期我们知道了统一接口请求的轻量级框架的封装那么我们轻量级框架封装还未结束我们本期继续介绍轻量级框架封装即日志监控、数据驱动以及断言等等二、轻量级框架封装日志监控封装日志在开发中是很重要的同时在自动化测试中也很重要因为日志它可以记录程序在运行的时候发生的一些细节信息从而帮助我们了解程序的运行时过程进一步帮助我们判断排除程序出现的问题。在Python中进行日志记录有两种内置标准库logging【常用】第三方库loggru我们会选择内置的标准库logging因为他能够和pytest很好的集成。1、在pytest中启用日志记录如何启用呢将下述的配置内容放入到我们的pytest.ini配置文件中# 日志相关配置 # 日志文件存储路径相对项目根目录日志会输出到logs文件夹下的frame.log文件log_file./logs/frame.log# 日志输出级别低于该级别的日志不会写入文件# 级别优先级从小到大DEBUG调试 INFO信息 WARNING警告 ERROR错误 CRITICAL严重故障log_file_levelINFO# 日志打印格式模板# %(asctime)s日志打印的时间# %(levelname)s日志级别名称INFO/WARNING等# %(message)s自定义输出的日志内容log_file_format%(asctime)s %(levelname)s %(message)s解释日志格式字符串占位符标识作用说明%(asctime)s打印日志记录的时间%(levelname)s打印日志级别文字DEBUG/INFO/WARNING等%(message)s打印自定义输出的日志/报错信息主体%(levelno)s打印日志级别对应的数字编号%(pathname)s打印当前执行文件完整路径等价于sys.argv[0]%(filename)s打印当前执行的程序文件名%(funcName)s打印输出日志所在的函数名%(lineno)d打印打印日志代码所在的行号%(thread)d打印当前线程ID数字%(threadName)s打印当前线程名称%(process)d打印当前进程ID数字上述我们只是将日志给启用但是日志里面的内容我们需要一个日志对象来进行封装。2、创建日志对象logger使用logging.getLogger(名字)来创建# 导入日志模块的包importlogging# 创建日志对象loggerlogging.getLogger(__name__)# 使用__name__可以自动生成名字loggerlogging.getLogger(my_logger)# 自己指定名字3、使用logger来记录日志用法如下所示# 导入日志模块的包importlogging# 创建日志对象loggerlogging.getLogger(__name__)# 使用__name__可以自动生成名字# 开始记录日志logger.debug()# 记录一个debug级别的日志logger.info()# 记录一个info级别的日志logger.error()# 记录一个error级别的日志注意日志的内容必须是字符串如果做到字符串我们使用一个占位符然后将数据填充进去最终我们的数据也变为字符串了# 这个输出格式我们在Python语法基础中也有介绍过的data{1,2,3}logger.error(f数据的内容{data})4、给接口打上日志记录上一期我们对接口请求进行了轻量级的统一封装importrequestsclassRequestUtil:# 首先将session做为类对象供给大家共用sessrequests.session()# 创建一个参数 用于共用公共参数params{application:app,application_client_type:android,}# 创建一个方法构造请求defsend_request(self,**kwargs):# 使用不定长的关键字参数# 完善动态参数ifparamsinkwargs:# 不存在就添加存在就是修改kwargs[params].update(self.params)# 发送请求respself.sess.request(**kwargs)returnresp那么现在我们就需要给这个所封装的接口请求打上我们的日志便于我们的观察我们需要打上哪一些日志呢前置# 导入日志框架importlogging# 创建出日志对象loggerlogging.getLogger(__name__)1、请求前# 1、打印请求入参日志请求前 logger.info(f【发起HTTP请求】原始请求参数:{kwargs})2、记录请求# 2、打印请求日志logger.info(f【请求参数合并完成】最终请求params:{kwargs.get(params)})3、记录响应# 3、打印响应日志请求后 logger.info(f【接口响应结果】状态码{resp.status_code}, 响应头{dict(resp.headers)})try:# 优先打印json格式响应体resp_jsonresp.json()# 因为只有你的响应内容是json字符串那么才可以使用json()方法logger.info(f【响应JSON数据】{resp_json})exceptException:# 非json接口打印原始文本logger.info(f【响应文本数据】{resp.text})完整代码importrequests# 导入日志框架importlogging# 创建出日志对象loggerlogging.getLogger(__name__)classRequestUtil:# 首先将session做为类对象供给大家共用sessrequests.session()# 创建一个参数 用于共用公共参数params{application:app,application_client_type:android,}# 创建一个方法构造请求defsend_request(self,**kwargs):# 使用不定长的关键字参数# 1、打印请求入参日志请求前logger.info(f【发起HTTP请求】原始请求参数{kwargs})# 完善动态参数ifparamsinkwargs:# 不存在就添加存在就是修改kwargs[params].update(self.params)# 2、打印请求日志logger.info(f【请求参数合并完成】最终请求params:{kwargs.get(params)})# 发送请求respself.sess.request(**kwargs)# 3、打印响应日志请求后 logger.info(f【接口响应结果】状态码{resp.status_code}, 响应头{dict(resp.headers)})try:# 优先打印json格式响应体resp_jsonresp.json()# 因为只有你的响应内容是json字符串那么才可以使用json()方法logger.info(f【响应JSON数据】{resp_json})exceptException:# 非json接口打印原始文本logger.info(f【响应文本数据】{resp.text})returnresp结果我现在day05这个目录下运行那么我们就会在当前目录下创建一个logs文件夹打开里面有一个frame.log文件梳理逻辑上述完成日志的封装之后我们接下来就实现数据驱动测试的封装三、轻量级框架封装数据驱动封装我们需要实现使用数据文件去驱动测试用例也就是代码和数据文件的分离。具体的实现思路设计YAML数据文件格式加载YAML完成数据驱动测试1、设计YAML数据文件格式数据文件名的格式需要和测试用例名的格式一致唯一的区别就是测试用例名的test_改为ddt_什么意思呢比如你的一个测试用用例是test_tan那么现在你这个测试用例所对应的YMAL文件命名为ddt_tan这样一来你一看都是tan那么你就可以知道哪一个测试用例对应了哪一个数据驱动文件。如下那么我们在数据驱动文件中写什么呢上述我们的数据文件中定制的有两个内容一个是Allure报告的定制另一个是接口请求的内容-feature:首页模块story:首页接口title:首页接口请求成功request:method:geturl:http://116.62.63.211/shop/api.phpparams:s:index/index2、加载YAML完成数据驱动测试怎么去读取数据呢就看下面的图解你要去读取数据那么你就得让一个东西来帮助我们这个东西其实就是一个标记pytest.mark.parametrizepytest.mark.parametrize(变量名,打开文件并读取)def用例():代码如下importallureimportpytestfrom commons.request_utilimportRequestUtilfrom commons.yml_utilimportYmlUtilpytest.mark.parametrize(case_info,YmlUtil(rE:\python_project\basic-python-grammar-learning\api_framwor\day06\ddt_tan.yaml).read())deftest_tan(case_info):# 读取数据文件中的内容 featurecase_info[feature]storycase_info[story]titlecase_info[title]requestcase_info[request]# 此处定制Allure报告 allure.dynamic.feature(feature)allure.dynamic.story(story)allure.dynamic.title(title)respRequestUtil().send_request(**request)# 请求完毕之后他会有返回值那么此时我们就可以断言assertresp.json()[code]0结果打开YAML文件中的文件地址可以动态获取Path(__file__)获取当前文件的路径str(Path(__file__).parent)得到当前文件所在的目录变动如下图所示代码importallureimportpytestfrom pathlibimportPathfrom commons.request_utilimportRequestUtilfrom commons.yml_utilimportYmlUtilcase_pathstr(Path(__file__).parent)pytest.mark.parametrize(case_info,YmlUtil(case_path/ddt_tan.yaml).read())deftest_tan(case_info):# 读取数据文件中的内容 featurecase_info[feature]storycase_info[story]titlecase_info[title]requestcase_info[request]# 此处定制Allure报告 allure.dynamic.feature(feature)allure.dynamic.story(story)allure.dynamic.title(title)respRequestUtil().send_request(**request)# 请求完毕之后他会有返回值那么此时我们就可以断言assertresp.json()[code]0结果四、轻量级框架封装JSON断言的封装我们会使用一种工具通过这个工具来对JSON对象进行一些深度的比较1、先安装对应的模块pip install deepdiff2、简单演示怎么使用我们假设有两个字典(JSON在Python中叫做字典)dict1{a:1,b:2,c:{d:3}}dict2{a:1,b:4,e:5}那么有以下的代码fromdeepdiffimportDeepDiff# 从deepdiff(从小写中)中导入DeepDiff大写dict1{a:1,b:2,c:{d:3}}dict2{a:1,b:4,e:5}diffDeepDiff(dict1,dict2)assertdiff{},diff# 如果是一样的话那么就断言成功了 后面的diff是为了打印详细信息3、deepdiff的特点1深度比较递归的比较有嵌套的数据结构2检测多种差异添加或者删除内容、值的变化、类型的变化3相等断言当两个数据一致(没有差异)时候返回的是空值可以使用结果{}进行断言。五、案例实战本实战中使用的接口文档是我们之前用的微信公众平台的接口文档老铁们可参考Jmeter接口实战1、基本样式创建test_weixin.py在里面写两个方法一个是用来获取鉴权码一个是用来上传文件的fromcommons.request_utilimportRequestUtil# 导入请求工具类deftest_get_token():passdeftest_upload():pass2、构造获取鉴权码的请求要素然后发送请求进行断言提取鉴权码get_ver{}# 全局变量deftest_get_token():methodGETurlhttps://api.weixin.qq.com/cgi-bin/tokenparams{grant_type:client_credential,appid:wx9335efa56e8cbb64,secret:0750c9411423c510fd0c2a1acdc32aa4}# 发送请求先实例化再掉里面的方法发送请求resRequestUtil().send_request(methodmethod,urlurl,paramsparams)# 断言expires_inres.json()[expires_in]assertexpires_in7200# 提取鉴权码access_tokenres.json()[access_token]get_ver[access_token]access_token3、我想只执行这个方法所以我就加一个标记pytest.mark.weixin此时需要在我们的配置文件中加入一个标记测试通过4、接下来就完成上传文件的这个接口那么将上述的获取鉴权码的接口复制一下进行修改即可因为大部分都是相似的得到的代码如下fromcommons.request_utilimportRequestUtil# 导入请求工具类importpytest get_ver{}# 全局变量pytest.mark.weixindeftest_get_token():methodGETurlhttps://api.weixin.qq.com/cgi-bin/tokenparams{grant_type:client_credential,appid:wx9335efa56e8cbb64,secret:0750c9411423c510fd0c2a1acdc32aa4}# 发送请求先实例化再掉里面的方法发送请求resRequestUtil().send_request(methodmethod,urlurl,paramsparams)# 断言expires_inres.json()[expires_in]assertexpires_in7200# 提取鉴权码access_tokenres.json()[access_token]get_ver[access_token]access_tokenpytest.mark.weixindeftest_upload():methodPOSTurlhttps://api.weixin.qq.com/cgi-bin/media/uploadimgparams{access_token:get_ver[access_token],}# 参数是文件files{media:open(rE:\python_project\basic-python-grammar-learning\api_framwor\data\弹简特头像.jpg,rb)# 文件的上传必须使用二进制的方式此处的路径我们可以使用之前的相对路径}# 发送请求先实例化再掉里面的方法发送请求resRequestUtil().send_request(methodmethod,urlurl,paramsparams,filesfiles)# 断言urlres.json()[url]asserthttpinurl结果通过六、总结接口自动化轻量级封装到目前我们轻量级的封装就暂时告一段落了我们接下来就总结一下我们的所学1、接口自动化测试的流程理解需求设计用例根据用例需求查找接口文档根据接口文档编写测试代码测试代码中包含请求的参数和预期的结果2、接口自动化测试中接口关联和数据驱动怎么做的接口关联先通过正则(字符串)或者JSONPATH(JSON)从上一个接口中提取数据把数据保存到全局变量中在下一个接口中使用变量即可完成关联数据驱动测试分析接口参数中会发生变化的内容不会变的东西不要用数据驱动将变化的部分写入yaml文件中因为YAML文件更便于阅读然后我们再编写代码从YAML文件中读取数据使用pytest的参数化标记进行数据驱动3、你们断言是怎么做的文本的响应类型判断包含或者相等实际上就是字符串之间的比较JSON的响应类型方法一使用JSONPATH提取目标数据对目标数据进行断言方法二DeepDiff对响应的内容进行断言4、你们的接口测试框架是怎么封装的首先我们要对技术栈有一个了解pytestrequestjsonpathallurelogging使用pytest作为一个基础的框架集成一些第三方插件对request进行一些统一请求的封装目的是进行公共参数的管理和日志的记录为了更方便的从json响应中提取数据进行管理和断言封装jsonpath利用allure进行测试报告的定制用例分组、自定义logo等等

相关新闻

90后35岁时我决定从运维转行:找一门越老越吃香的职业!

90后35岁时我决定从运维转行:找一门越老越吃香的职业!

90 后 35岁时我决定从运维转行:找一门越老越吃香的职业! 35岁之前,我总认为运维这个职位只要能熬得住、愿意加班的话,就一定能够熬出头来。但是真正做了几年之后才明白过来,巡检、处理报警、半夜救火等事情已经成为了…

2026/7/23 20:50:41 阅读更多 →
油田通信维护进入集成时代|鼎讯 RM-1000 与一线运维模式探索

油田通信维护进入集成时代|鼎讯 RM-1000 与一线运维模式探索

在石油行业,通信维护是一项 “看不见” 的工作,却直接影响着生产的 “看得见” 的效率。 从钻井平台到输油管道,从炼化基地到储油库区,每一个环节的通信设备都需要定期检测和维护。过去,这项工作依赖多个独立仪器配合完…

2026/7/23 20:49:41 阅读更多 →
智能体测开Day4

智能体测开Day4

昨日回顾今日讲解vi 编辑文件命令搜索命令替换命令创建session连接别人的Linux1.首先找到vmware中编辑->虚拟网络编辑器->选择仅主机点击更多设置->选择NAT模式->选择NAT设置->主机端口选择一个未被占用的端口号->虚拟机IP地址查找CentOS的IP->虚拟机端口…

2026/7/23 20:49:41 阅读更多 →

最新新闻

【养老照护微项目管理实务连载】4.1 规划进度管理

【养老照护微项目管理实务连载】4.1 规划进度管理

规划进度管理是养老照护微项目在完成范围界定、任务分解后开展的时间维度全局性规划过程,是规范照护服务时序、节奏、周期、频次与进度管控逻辑的核心环节。本过程围绕按时、有序、衔接顺畅、频次达标、节奏稳定的原则,制定统一、可落地的照护进度管理规…

2026/7/23 20:58:46 阅读更多 →
毕业设计:基于SpringBoot和Vue的化妆管理系统(源码)

毕业设计:基于SpringBoot和Vue的化妆管理系统(源码)

目录 一、项目背景 二、技术介绍 三、功能介绍 四、代码设计 五、系统实现 一、项目背景 随着社会经济的快速发展和人们生活水平的不断提高,化妆品已成为现代人日常生活中不可或缺的消费品。据统计,我国化妆品市场规模持续扩大,线上线下…

2026/7/23 20:58:46 阅读更多 →
【开篇词】为什么要学习指纹浏览器,学习指纹浏览器能为我们带来什么?

【开篇词】为什么要学习指纹浏览器,学习指纹浏览器能为我们带来什么?

更多内容请见: 《指纹浏览器开发实战》 - 专栏介绍和目录 文章目录一、从一个常见困境说起二、什么是浏览器指纹?2.1 指纹不是某一个字段,而是「环境组合」2.2 指纹浏览器的定义2.3 指纹浏览器 vs 其他方案:怎么选?2.4…

2026/7/23 20:58:46 阅读更多 →
linux的rename命令详解

linux的rename命令详解

Linux rename 命令超详细详解rename 是 Linux 系统中批量重命名文件 / 目录的专用命令,相比 mv 配合循环的写法更简洁高效。但它有两个语法完全不兼容的主流实现,这是绝大多数用户踩坑的根源:Perl 版 rename(prename)&…

2026/7/23 20:58:46 阅读更多 →
基于TI C2000 FCL与SFRA的双轴PMSM伺服驱动实战指南

基于TI C2000 FCL与SFRA的双轴PMSM伺服驱动实战指南

1. 项目概述在工业伺服驱动和机器人等高精度运动控制领域,对电流、速度和位置环的控制性能要求极为苛刻。其中,电流环作为最内层的控制回路,其响应速度(即带宽)直接决定了整个系统的动态性能上限。传统基于MCU的方案&a…

2026/7/23 20:58:45 阅读更多 →
【项目编号project16578】|SpringBoot智慧小区服务管理系统:物业报修、公告缴费与社区服务一体化

【项目编号project16578】|SpringBoot智慧小区服务管理系统:物业报修、公告缴费与社区服务一体化

技术栈:SpringBoot MySQL摘要:智慧小区服务管理系统适合围绕物业服务闭环展开,包括业主信息、报修处理、公告发布、缴费记录和后台管理等模块。关键词:project16578、智慧小区服务管理系统、SpringBoot、项目实战一、项目概述智慧…

2026/7/23 20:57:45 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/23 17:49:47 阅读更多 →

月新闻