pytest+request+yaml+allure搭建低编码调试门槛的接口自动化框架

接口自动化非常简单,大致分为以下几步:

  1. 准备入参
  2. 调用接口
  3. 拿到2中response,继续组装入参,调用下一个接口
  4. 重复步骤3
  5. 校验结果是否符合预期

一个优秀接口自动化框架的特点:

  1. 【编码门槛低】,又【能让新手学到技术】
  2. 【低调试门槛】
  3. 【优秀的可读性】
  4. 【很好的可维护性】
  5. 能很【方便多人协同】,以便【自动化代码能不断积累】形成规模效应,且【自动化case覆盖率可量化】
  6. 有失败重试机制,克服环境的不稳定
  7. 【清晰的测试报告】
  8. 能【低成本且灵活地触发】(指定环境、指定时间、指定范围)

综上,我们需要搭建一个同时满足以上特点的轻量级接口自动化框架

首先,管理接口

    达成:【编码门槛低】【方便多人协同】【优秀的可读性】【很好的可维护性】

  • 被测接口单独管理,目录结构和和开发使用的yapi保持一致,统一放置在仓库下,“接口管理”目录中;如下:

        

  • 每个接口使用yaml文件管理,如下,且使用中文命名增加可读性。
  • method: post
    host: "${host}"
    url: /copy/trading/v1/follower/edit
    headers:{token: "799b72f3f94973f5a54a54204eac96a1aa94cd5d365245929098e921b2ddc154"}
    body:{"followType": 1,"traderUid": 102806,"margin": "100","followAmount": "1000","stopLossRation": null,"positionMode": 1,"positionModeConfig": 0,"leverModeConfig": 0,"leverage": 1,"marginModeConfig": 0,"marginMode": 0,"positionRisk": null,"slippage": "0.006",}
    response:code: # 响应码(0: 成功)msg: #  返回描述(code为0时,返回:成功)data: # 响应数据
  • 调用接口时,默认用yaml文件中的参数(剔除response,response只做示例用),如需替换,会在调用过程中,标记具体需要替换的key value即可,如下,方便快捷
  • r.invoke_api("更新用户配置.yaml", headers={"token": 'trader_son_token'}, body={"positionMode": 1})

其次,编写代码,调用接口

        达成:【编码门槛低】【优秀的可读性】【低调试门槛】【清晰的测试报告】

  • 封装requests包,使用requests.session(),根据上述接口文档,调用get或post方法,且使用allure将入参和返回都放置到测试报告里面,且此块代码无需实际接口测试同学关注。【能让新手学到技术】
  • class RequestUtil:def invoke_api(self, api, headers=None, body=None):"""解析需要调用的接口,并且进行参数替换,基础断言等:param api: 需要调用的接口:param header: 需要传入的请求头:param body: 需要传入的请求体:return: 返回接口响应的结果"""api_name = apiparam = YamlUtil.parse_api(api_name)if headers is not None:for key in headers:param['headers'][key] = headers[key]if body is not None:for key in body:param['body'][key] = body[key]params = self.replace_value(param)with allure.step(f"步骤:{api_name}"):response = self.send_request(params)if self.run_mode == 1:print("")print(f"调用接口:{api_name}")print(params)print(response)return responseelse:return responsedef send_request(self, *args):"""发起接口请求:param args: 接口请求的参数:return: 接口返回的数据"""method = args[0]['method'].lower()ip = self.replace_value(args[0]['host'])url = ip + args[0]['url']headers = args[0]['headers']body = args[0]['body']data = bodyif method == "get":res = self.sess.get(url, params=data, headers=headers)elif method == "post":if 'files' in args:files = args[0]['files']file_path = os.path.join(YamlUtil.data_file_path, files)with open(file_path, 'rb') as file:files = {'file': ('image.jpg', file)}res = self.sess.post(url, files=files, headers=headers)res = self.sess.post(url, json=data, headers=headers)else:print("请求方式错误")try:res = res.json()with allure.step(f"URL:{url}"):...with allure.step(f"Method:{method}"):...with allure.step(f"Headers:{json.dumps(headers)}"):...with allure.step(f"Body:{json.dumps(data, ensure_ascii=False)}"):...with allure.step(f"Response:{json.dumps(res, ensure_ascii=False)}"):return resexcept Exception as e:print("该接口返回的结果不是json数据?")res = res.textwith allure.step(f"URL:{url}"):...with allure.step(f"Method:{method}"):...with allure.step(f"Headers:{json.dumps(headers)}"):...with allure.step(f"Body:{json.dumps(data, ensure_ascii=False)}"):...with allure.step(f"Response:{json.dumps(res, ensure_ascii=False)}"):return res
  • 通过pytest的fixture装饰器,将RequestUtil注入进去每个测试用例里面去
  • @pytest.fixture(scope="session")
    def r():return RequestUtil()
    

  • 测试编码同学只需要使用方法,即可完成接口调用和response获取
  • 接口:百度.yaml
  • method: post
    host: https://ug.baidu.com
    url: /mcp/pc/pcsearch
    headers:{}
    body:{"errno": 0,"errmsg": "ok","data": {"log_id": "1652589279","action_rule": {"pos_1": [],"pos_2": [],"pos_3": []}}}

    事实上,测试代码只有这么点:【编码门槛低】只需要能看懂接口文档,和http的基本知识,以及知道Python的字典和assert,便可轻松完成编码

    def test_百度(r):#其中 r为fixture装饰器,通过conftest.py注入进去resdic= r.invoke_api("百度.yaml",headers={},body={})assert resdic[errmsg] == "ok"
    assert resdic[data][log_id] == "3277317105"
  • 不管成功失败,测试报告都会打出每一次请求的入参和返回,如下图,都不用在IDE里面调试。【低调试门槛】【清晰的测试报告】
  • 另外,数据驱动的case,用如下的方式编写
  • import pytest@pytest.mark.parametrize('emails,password,assert1', [('11111@qq.com', 'Tset111', 'success'),('22222@qq.com', 'Tset222', 'fail'),('33333@qq.com', 'Tset333', 'error'),
    ])
    def test_注册用户(r, emails, password, assert1):response_info = r.invoke_api('注册用户.yaml', body={"emails": emails, "password": password})assert response_info['data'] == assert1
    

再次,测试用例的组织和结构

        达成:【方便多人协同】【自动化代码能不断积累】【自动化case覆盖率可量化】

  1. 手工用例遵循实际的业务模块树形结构,做较精细的模块拆分
  2. 末级手工用例使用xmind管理,作为用例树的末级,标题上按如下打标:哪些场景需要被覆盖(目标)?已被覆盖(进度)?功能覆盖率多少(量化)?哪些地方还需要验证前端?一目了然,工时评估更透明
    • 是否需要自动化
    • 是否已被自动化
    • 是否还需要验证前端
  3. 自动化测试用例目录,和手工用例目录保持一致,
  4. 每个自动化case一个.py文件,自动化测试用例名与手工测试名保持一致。如此保障一一对应
  5. 如若涉及一对多:
    1. 如果涉及单接口的,自动化测试用例名与手工用例末级目录一致;
    2. 如果涉及数据驱动的,自动化测试用例名与手工用例末级目录一致;
  6. 通过以上措施,很方便计算出自动化case覆盖率(分子为已完成自动化case,分母为达标为:需要自动化的case数)

再次,通过配置文件,和参数化运行

        达成【低成本且灵活地触发】

  • yaml方式的配置文件
  • run_mode: 2 # 1调试模式/2正式模式
    run_env: one  # 运行脚本环境test:host: http://api.test.xyzdb:host:port:user:password:redis:host:password:testa:host: http://api.testa.xyzdb:host:port:user:password:redis:host:password:# 环境
    one:# 接口地址host: # b连接信息db:host:port:user:password:# redis连接信息redis:host:password:
  • main函数运行的时候,拿到具体运行的环境信息,读取对应的配置
  • import os
    import pytest
    from pytest_jsonreport.plugin import JSONReport
    import argparsefrom Core.parse_yaml import YamlUtil
    from Core.robot_utils import Robotdef main(env):YamlUtil.clear_env_yaml()if env.env is not None:e = env.envdata = {"env": e}YamlUtil.write_env_yaml(data)current_path = os.path.dirname(os.path.abspath(__file__))json_report_path = os.path.join(current_path, 'report/json')html_report_path = os.path.join(current_path, 'report/html')plugin = JSONReport()pytest.main(["自动化用例/百度搜索.py", '--alluredir=%s' % json_report_path, '--clean-alluredir'], plugins=[plugin])# 生成allure报告os.system('allure generate %s -o %s --clean' % (json_report_path, html_report_path))os.system('allure open %s' % html_report_path)if __name__ == "__main__":parser = argparse.ArgumentParser()parser.add_argument("--env", help="参数为需要执行的环境")args = parser.parse_args()main(args)
  • #在testa环境运行
    python run.py --env testa

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

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

相关文章

三轴云台之RTSP流分辨率

三轴云台是一种能够在三个轴向上(通常是俯仰、偏航和滚动轴)准确、稳定地控制其负载(如相机、传感器等)位置和姿态的设备。而RTSP(Real Time Streaming Protocol)是一种网络控制协议,用于控制媒…

Facebook 隐私变革之路:回顾与展望

在数字时代,个人隐私的保护一直是社交平台面临的重大挑战之一。作为全球最大的社交网络平台,Facebook(现为Meta)在处理用户隐私方面的变革,历经了多次调整与完善。本文将回顾Facebook在隐私保护方面的历程,…

STM32 USB组合设备 MSC CDC

STM32 USB组合设备 MSC CDC实现 教程 教程请看大佬niu_88 手把手教你使用USB的CDCMSC复合设备(基于stm32f407) 大佬的教程很好,很详细,我调出来了,代码请见我绑定的资源 注意事项 值得注意的是: 1、 cu…

【C盘清理】C盘清理工具、Unity缓存文件转移

链接: https://pan.baidu.com/s/1yE_7qF741o4NmBIsrd3XzA?pwdbwnn CCleaner 用于清理磁盘垃圾 勾选你要分析的选项,点击分析,分析完毕后,点击清理。 主要别清错东西了。(可以不要勾选网络缓存、网络记录相关的选项&#xff0…

无需昂贵GPU:本地部署开源AI项目LocalAI在消费级硬件上运行大模型

无需昂贵GPU:本地部署开源AI项目LocalAI在消费级硬件上运行大模型 随着人工智能技术的快速发展,越来越多的AI模型被广泛应用于各个领域。然而,运行这些模型通常需要高性能的硬件支持,特别是GPU(图形处理器&#xff09…

用户注册模块用户校验(头条项目-05)

1 用户注册后端逻辑 1.1 接收参数 username request.POST.get(username) password request.POST.get(password) phone request.POST.get(phone) 1.2 校验参数 前端校验过的后端也要校验,后端的校验和前端的校验是⼀致的 # 判断参数是否⻬全 # 判断⽤户名是否…

Sui Move:基本概览一

Module (模块) Move 代码被组织成模块, 可以把一个模块看成是区块链上的一个智能合约 可以通过调用这些模块中的函数来与模块进行交互,可以通过事务或其他 Move 代码来实现, 事务将被发送到并由Sui区块链进行处理,一旦执行完成,结果的更改将…

git 删除当前目录下的所有文件, 重新拉取分支内容

如果你想删除当前目录下的所有文件并重新拉取分支内容,可以按照以下步骤操作。请注意,这将永久删除本地未提交的更改,请确保你已经备份了重要文件。 步骤 1:删除当前目录下的所有文件 运行以下命令删除当前目录下的所有文件&…

[mysql] mariabackup增量备份数据库

增备测试 1. 使用命令,进行一次全备full_back_date mariabackup -u root -p 123456 --backup --target-dir/dbbackup/full_back_$(date %F_%H%M%S)2. 插入一些数据,进行第一次增备full_back_date_inc_date insert into test2.product values (100,"黄金屋1&…

matlab的绘图的标题中(title)添加标量以及格式化输出

有时候我们需要在matlab绘制的图像的标题中添加一些变量,这样在修改某些参数后,标题会跟着一块儿变。可以采用如下的方法: x -10:0.1:10; %x轴的范围 mu 0; %均值 sigma 1; %标准差 y normpdf(x,mu,sigma); %使用normpdf函数生成高斯函数…

微服务的自我修养:从拆分到秩序的进化论

文章背景 还记得我第一次接触微服务的场景,那是一个炎热的夏天。系统上线的前一天,单体应用出了点小问题,结果整个平台瘫痪了!所有人手忙脚乱修复,但复杂的代码逻辑让进度异常缓慢。 后来听说可以用微服务架构来拆分系…

YOLOv8从菜鸟到精通(二):YOLOv8数据标注以及模型训练

数据标注 前期准备 先打开Anaconda Navigator,点击Environment,再点击new(new是我下载anaconda的文件夹名称),然后点击创建 点击绿色按钮,并点击Open Terminal 输入labelimg便可打开它,labelimg是图像标注工具,在上篇…

【c语言】指针 (完结)

一、sizeof和strlen的对比 1、sizeof 前面我们在学习操作符的时候,我们学习了sizeof,知道其是计算变量所占内存的大小的,单 位是字节,如果操作数是数据类型的话,计算的就是这个类型的变量所占的内存空间的大…

成语知识竞赛主持稿及串词

一、开场白 A:尊敬的各位老师 B:亲爱的同学们 合:大家好! A:冬日的暖阳带着青春的气息扑面而来,我们迎来了XXX中学精英成语知识大赛。 B:欢迎各位来到成语大赛的现场。 A:成语是中华…

人工智能:人形机器人的开发需求会创造哪些热门的就业岗位?

人形机器人的开发需求会创造以下热门的就业岗位: 研发设计类 机械结构工程师:负责设计人形机器人的机械本体结构,包括关节、骨架、外壳等,需要对机械原理、力学知识有深入理解,熟悉使用CAD、SolidWorks等设计软件。电…

【Rust】结构体定义域实例化

目录 思维导图 1. 结构体的定义与实例化 1.1 结构体的基本概念 1.2 定义结构体 1.3 创建结构体实例 1.4 结构体的定义与实例化示例 2. 访问与修改结构体字段 2.1 访问字段 2.2 修改字段 3. 结构体实例的构造函数 3.1 构造函数的定义 3.2 使用字段初始化简写 4. 结…

vue2修改表单只提交被修改的数据的字段传给后端接口

效果: 步骤一、 vue2修改表单提交的时候,只将修改的数据的字段传给后端接口,没有修改得数据不传参给接口。 在 data 对象中添加一个新的属性,用于存储初始表单数据的副本,与当前表单数据进行比较,找出哪些…

Docker 安装开源的IT资产管理系统Snipe-IT

一、安装 1、创建docker-compose.yaml version: 3services:snipeit:container_name: snipeitimage: snipe/snipe-it:v6.1.2restart: alwaysports:- "8000:80"volumes:- ./logs:/var/www/html/storage/logsdepends_on:- mysqlenv_file:- .env.dockernetworks:- snip…

迁移WSL中的ext4.vhdx文件

文章目录 环境前言过程参阅 环境 Windows11(WSL2) 前言 今天发现系统C盘的磁盘空间已经严重不足,查找后发现有一个很大的 ext4.vhdx 文件,位置在: C:\Users\ljfro\AppData\Local\Packages\CanonicalGroupLimited.U…

Windows 11更新之后卡顿 (黑神话掉帧严重)问题探索

前提 Windows 11 晚上更新完 24h2 之后,第二天玩黑神话,才40多帧 之前开启插针,可以运行到 120 帧左右 我的配置 9600X 3080 版本退回 用系统自带的 goBack 版本退回 大概不到3分钟 帧数还是不对,于是重做了系统 重做系统 …