接口测试框架实战 | 通用 API 封装实战

news/2024/10/31 5:36:56/

接口测试仅仅掌握 Requests 或者其他一些功能强大的库的用法,是远远不够的,还需要具备能根据公司的业务流程以及需求去定制化一个接口自动化测试框架的能力。所以,接下来,我们主要介绍下接口测试用例分析以及通用的流程封装是如何完成的。

接口测试用例分析

首先在做用例分析之前,可以通过追查公司一年来所有的故障原因,定位问题起因,或者通过与 CTO、产品经理、研发、运维、测试调查,得到质量痛点,还可以分析业务架构、流程调用,以及监控系统了解到业务的使用数据,从而得到质量需求

得到质量需求之后,通过与产品经理、项目经理、研发总监等对接后得知待测业务范围、业务场景用例、业务接口分析,从而确定公司的测试计划。将测试计划与质量需求结合进行分析,就可以开始进行业务用例的设计,而接口测试用例分析,也在其内。

质量需求样例
测试痛点公司的接口一直不稳定影响用户的使用
质量反馈最近半年来出现了几次大的故障
回归测试每次升级都会影响老的功能
测试策略目前公司没有可靠的测试体系
重构测试微服务话改造需要有良好的测试体系保证

接口测试封装思想

接口封装思想主要分为 3 个大维度:配置、接口封装、业务流程。其中:

  • 配置主要用作根据配置文件获取初始配置和依赖;

  • 接口封装遵循 APIObject 设计模式,对接口的调用进行抽象封装;

  • 业务流程则负责数据初始化、业务用例设计,包含有多个 API 形成的流程定义,不要再包含任何接口实现细节、以及断言。

下面将会与实战案例结合,进行详细的介绍。

基于加密接口的测试用例设计

由于信息安全原因,许多接口在传输的时候会对请求与响应进行加密处理,如果直接对这部分数据做断言显然是行不通的。还需要对这部分接口额外进行解密的处理之后,才可以对已解密的接口进行断言。

环境准备

在进行实战之前,需要先准备一个对响应加密的接口。对它发起一个 get 请求后,得到一个加密过后的响应信息。

先准备一个 JSON 格式 demo:

{"topics":
{
"orange":"movie",
"shool":"testing-studio",
"president":"seveniruby"
}
}

使用 base64 对其做加密,得到一个加密后的文件 demo64.txt

base64 demo.json >demo64.txt

使用 Python 命令在 “demo64.txt” 所在目录启动一个服务

python -m http.server 10000

使用curl命令对这个服务进行get请求:

curl http://127.0.0.1:10000/demo64.txt

如果请求成功的话就代表环境已经准备成功

实战练习

调用 base64,直接对返回的请求做解密,即可得到解密后的响应,将解密后的响应转为 JSON 格式,此时就可以对这个返回值做断言且不会报错了。

import base64
import json
import requests
class TestEncode:url = "http://127.0.0.1:10000/demo64.txt"def test_encode(self):r = requests.get(self.url)encode = json.loads(base64.b64decode(r.content))assert encode["topics"]["president"] == "seveniruby"

这样的写法显然不够优雅,如果被测接口的协议发生变化,Requests 库无法支持改变后的协议,需要调用别的第三库发送请求信息,则还是需要修改底层的源码。碰到这种情况,可以增加一层封装,构造一层更加通用的发送方法。

首先需要通过一个字典的结构体,保存所有的请求信息,包括发送的协议、解码方式、请求 method 等等,而这种字典形式的结构体也为后面的数据驱动改造做好了一个重要的铺垫。

 req_data={"schema": "http","method": "get","url": "http://127.0.0.1:10000/demo64.txt","headers": None}

通过请求信息的结构体中的schema,添加判断条件,去选择不同的请求协议。举个例子,如果 schema 为“http”的话,就选择调用被封装的 requests 库。

class ApiRequest:#构造send方法,通过def send(self, data: dict):if "http" == data["schema"] :res = requests.request(data["method"],data["url"],header=data["headers"])return json.loads(base64.decode(res.content))elif "dubbo" ==  data["schema"]:passelif "websocket" == data["schema"]:passelse:pass        

调用在ApiRequest类中的send方法发送请求并进行断言

class TestEncode:def test_api(self):req_data={"schema": "http","encoding": "base64","method": "get","url": "http://127.0.0.1:10000/demo64.txt","headers": None}re = ApiRequest()data = re.send(req_data)assert data["topics"]["president"] == "seveniruby"

如果面对不同的算法,还需要修改底层的源码,所以需要把算法封装。需要使用哪个算法,就使用哪个。封装的思想与上面相同。首先在字典结构体中添加一个 encoding 字段,用来判断选择的不同的加密条件。

 req_data={"schema": "http","method": "get","url": "http://127.0.0.1:10000/demo64.txt","headers": None,"encoding": "base64"}

还是通过请求信息的结构体中的 encoding,添加判断条件,去选择不同的解密方式。

class ApiRequest:def send(self, data: dict):if "http" == data["schema"] :res = requests.request(data["method"],data["url"],headers=data["headers"])return json.loads(base64.b64decode(res.content))#通过请求信息的结构体中的`encoding`,去选择不同的解密方式。if data["encoding"] == "base64":return json.loads(base64.b64decode(res.content))elif data["encoding"] == "private":return json.loads(requests.post("url", data=res.content).content)else:return json.loads(res.content)

总结

首先需要明确在面对一个加密的响应结果,可以使用什么样的处理方式:

  1. 如果知道使用的是哪个通用加密算法的话,可以自行解决。

  2. 如果不了解对应的加密算法的话,可以让研发提供加解密的 lib。

  3. 如果既不是通用加密算法、研发也无法提供加解密的 lib 的话,可以让加密方提供远程解析服务,这样算法仍然是保密的。

本文主要讲的是在了解使用加密算法的情况下,如何处理这样的解密算法。但是封装的思路都是相通的,不管是面对哪种情况,都可以通过格式化的数据,指明数据的内容,并通过一层逻辑的封装,将加解密或者选择的协议封装进去。

 

在 APIObject 设计模式中,需要一个 base_api 作为其他 API 步骤的父类,把通用功能放在这个父类中,供其他的 API 直接继承调用。这样做的优点在于,减少重复代码,提高代码的复用性。

实战

在上一章节在演示使用 API-Object 设计模式对脚本进行改造时提到了 base_api。不过在上一章,仅仅只是封装了一个 utils 中的一个简单方法。并没有完全体现出 base_api 的实际作用。

接下来,我们通过通用接口协议的定义与封装实战,来实际体会一下 base_api 的巧妙之处。

  • base_api.py

在代码内,对 request 进行一层封装,当然在这里还看不出来具体的优势:

import requestsclass BaseApi:def request(self, method, url, **kwargs):self.json_data = requests.request(method=method, url=url, **kwargs)return self.json_data

  • wework.py

继承于类 BaseApi,可以直接调用父类中的 request 方法(不需要导入 requests 库),从而发起一个 get 请求:

from test_interface.test_wework.api.base_api import BaseApiclass WeWork(BaseApi):corpid = "ww93348658d7c66ef4"contact_secret = "T0TFrXmGYel167lnkzEydsjl6bcDDeXVmkUnEYugKIw"token = dict()token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"def get_access_token(self):r = self.request(method="get", url=self.token_url,params={"corpid": self.corpid, "corpsecret": self.contact_secret})return r.json()

  • test_wework.py

继承于类 WeWork,主要目的只是为了检查上面的 get_access_token(self) 是否成功:

from test_interface.test_wework.api.wework import WeWorkclass TestWeWork(WeWork):def test_get_access_token(self):r = self.get_access_token()assert r["errcode"]==0

以上,在上面的案例中,在 base_api.py 中对 requests 进行了多一层的封装,这样只要是属于 BaseApi 这个类的子类,都可以无需引用而直接调用 requests 库。从而发起各种各样的请求,实现了通用接口协议的定义与封装。

 


http://www.ppmy.cn/news/271487.html

相关文章

中国传统色的雅称——你可知?

梅染、荼白、落栗、薄柿、酡颜、踯躅、曙色、缁色、鸦青、胭脂、若草、缟、缃色、竹青、苏芳、缥色、天水碧、月白、远山如黛、青梅煮酒、桥下春波。 这些颜色的名字,是不是看着美极了。 中国传统颜色的雅称,你都知道吗? 梅染 梅染顾名思义&a…

分享一组超喜欢的粉色樱花高清壁纸~

向往漫天的樱花?想要一款治愈系的桌面大图?推荐粉色樱花高清壁纸给大家使用,壁纸粉色设计,温婉柔和超治愈,为您带来好心情

多套头像/壁纸/背景图资源微信小程序源码 粉色UI 带流量主

云开发版粉色UI微信小程序源码,背景图、头像、壁纸小程序源码,带流量主功能。 云开发小程序源码无需服务器和域名即可搭建小程序另外还带有流量主功能噢!微信平台注册小程序就可以了。 这套粉色UI非常的好看,里面保护有背景图、…

粉色的牡丹花Mac动态壁纸

丹花有着花中之王的美名,其雍容华贵的外形十分让人喜爱。 粉色的牡丹花动态壁纸

6k高清Mac粉色动态壁纸

5k高清粉色动态壁纸分享,壁纸非常的精致唯美,有可爱的花朵,希望你们会喜欢! 6k高清粉色动态壁纸

Python进阶-----面对对象5.0(面对对象三大特征之--多态)

目录 前言: 多态 习题 前言: 上一期讲了Python面对对象中的继承,而今天讲的是多态,其实多态跟继承是紧密相关的,换句话说多态是继承的一种表现形式,下面就一起来看看吧!(上一期链…

cdialog 多次更换背景图_INS少女心背景图来袭:山外青山楼外楼,我的少年百分九!...

壁纸 大师级公众号 每天更新壁纸头像背景图 关注 温馨提示:新朋友阅读本文前,请您先点击上面的蓝色字体“剧透剧”,再点关 注这样您就可以继续免费收到微丧背景图文章了,每天都有分享,完全是“免费订阅”,请…

粉色的专属待遇

粉色的专属待遇 作者:小 M 在五颜六色的彩盒中,我一直认为每一种色彩都可以绘画不一样的风景,而今年的夏天,粉色给了我独一无二的桃源生活。 一直不迷信的我,在闺蜜的陪伴下,我慢慢的进入我曾不相信的…