深度解析接口自动化框架封装项目:封装层级,关联调用,极限改进

 

目录

 前言:

一、接口封装与封装层级

二、接口关联和数据准备

三、接口封装极限改进

四、代码示例

五、总结


 前言:

接口自动化是软件测试领域中的一个重要环节,它可以自动化执行接口测试用例,快速发现和定位接口问题,提高软件的质量和稳定性。为了实现接口自动化的高效执行和管理,我们需要开发一个接口自动化框架。

本文将分享一个基于Python语言实现的接口自动化框架封装项目实战,重点介绍了如何对接口进行关联封装和极限改进,从而提高接口自动化框架的可靠性和扩展性。

一、接口封装与封装层级

接口封装是指将一个或多个接口进行封装,封装成一个更高层次的接口,使得接口调用更加方便和简洁。接口封装一般分为三个层级:

1、基础封装层:将底层的接口进行封装,提供基本的请求和响应信息。

2、逻辑封装层:在基础封装的基础上,将接口的输入参数和输出结果进行组合,形成更为高层次的功能。

3、业务封装层:在逻辑封装层的基础上,将多个接口进行关联调用,形成更为完整的业务场景。

举个例子,我们现在要开发一个接口自动化框架来测试某个电商平台的商品查询接口,那么我们就需要对该接口进行封装。假设该接口需要输入一个商品名称,返回该商品的详细信息,那么我们可以使用下面的代码进行基础封装:

import requests

class GoodsApi:
    
    def __init__(self):
        self.base_url = "https://xxx.com/api/goods"
    
    def query_good(self, name):
        url = f"{self.base_url}/{name}"
        response = requests.get(url)
        return response.json()

在基础封装层的基础上,我们可以继续封装逻辑层和业务层。如果需要查询某个分类下的商品信息,那么逻辑封装层的代码可以是这样的:

class CategoryApi:
    
    def __init__(self):
        self.base_url = "https://xxx.com/api/category"
        
        self.goods_api = GoodsApi()
    
    def query_category_goods(self, category_name):
        category_info = self.query_category(category_name)
        goods_info = []
        for goods_name in category_info.get('goods'):
            good_info = self.goods_api.query_good(goods_name)
            goods_info.append(good_info)
        
        return goods_info
    
    def query_category(self, category_name):
        url = f"{self.base_url}/{category_name}"
        response = requests.get(url)
        return response.json()

在业务封装层中,我们可以将多个接口进行组合,形成更为完整的业务场景。例如,我们想要查询某个用户的所有订单信息,那么可以这样封装:

class UserApi:
    
    def __init__(self):
        self.base_url = "https://xxx.com/api/user"
        
        self.category_api = CategoryApi()
    
    def query_user_order(self, user_id):
        user_info = self.query_user(user_id)
        order_info = []
        for category_name in user_info.get('order_category'):
            order_goods = self.category_api.query_category_goods(category_name)
            order_info.extend(order_goods)
        
        return order_info
    
    def query_user(self, user_id):
        url = f"{self.base_url}/{user_id}"
        response = requests.get(url)
        return response.json()

在这个例子中,我们将查询用户信息、查询分类下的商品信息以及查询用户订单三个接口进行了关联封装,使得调用用户订单信息的代码可以更加简洁和易读。

二、接口关联和数据准备

在进行自动化接口测试时,我们经常需要将多个接口进行关联调用和数据传递,这就需要在接口封装的基础上,加入关联和数据准备的功能。

关联指的是需要使用前一个接口的返回数据作为后一个接口的输入参数,这种情况下,我们需要用到一个Session对象,保存前后两个请求之间的关联关系。下面是一个示例代码:

class SessionApi:
    
    def __init__(self):
        self.session = requests.Session()
        self.base_url = "https://xxx.com/api"
        
        self.goods_api = GoodsApi(self.session)
        self.category_api = CategoryApi(self.session)
        self.user_api = UserApi(self.session)
    
    def login(self, user_id, password):
        url = f"{self.base_url}/login"
        data = {
            'user_id': user_id,
            'password': password
        }
        response = self.session.post(url, data=data)
        return response.json()
    
    def query_user_order(self, user_id):
        user_info = self.user_api.query_user(user_id)
        order_info = []
        for category_name in user_info.get('order_category'):
            order_goods = self.category_api.query_category_goods(category_name)
            order_info.extend(order_goods)
        
        return order_info

在这个例子中,我们在Session对象中保存了每个封装层级的实例对象,将前面的请求的Session对象传递给后面的请求,实现接口关联。我们还新增了一个login方法,用于模拟用户登录,获取到Session对象,保证后续接口调用的完整性和正确性。另外,我们还可以在数据准备中,对请求所需要的数据进行随机生成或从数据库中读取,以提高接口自动化测试的可靠性和稳定性。

三、接口封装极限改进

在前面的示例中,我们只给出了基础、逻辑和业务封装的三个层级,但实际的项目中,我们可能还需要对接口进行更为细粒度的封装。比如,对于接口的请求参数、响应参数、错误码和异常情况,我们都可以进行更为细致和个性化的封装。下面是一个示例代码:

class GoodsApi:
    
    def __init__(self, session):
        self.session = session
        self.base_url = "https://xxx.com/api/goods"
    
    def query_good(self, name):
        url = f"{self.base_url}/{name}"
        response = self.session.get(url)
        return self._parse_response(response)
    
    def _parse_response(self, response):
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"request failed with status code {response.status_code}")

在这个示例代码中,我们新增了一个_parse_response方法,用于解析响应结果。如果响应状态码不是200,那么会抛出异常;否则,返回json格式的响应结果。这个方法可以避免我们在每个接口调用的时候,都需要重复编写解析响应结果的代码。

除了对接口的整体封装,我们还可以进行模块化的封装。在一个大型的项目中,可能会有多个功能模块,每个功能模块内部又包含了多个接口,这时我们可以对每个功能模块进行封装,将其内部的接口进行模块化的管理和维护。这样做的好处是,提高了代码的可读性和可维护性,降低了代码的耦合度,方便日后的功能模块扩展和维护。

class GoodsModule:
    
    def __init__(self, session):
        self.goods_api = GoodsApi(session)
    
    def query_good_info(self, good_name):
        return self.goods_api.query_good(good_name)
    
    def query_good_price(self, good_name):
        good_info = self.goods_api.query_good(good_name)
        return good_info.get('price')

在这个示例代码中,我们将商品模块的两个接口,分别封装成为两个函数,query_good_info和query_good_price,使得调用商品模块内部的接口更加方便和简洁。

四、代码示例

下面是一个完整的示例代码,包括样例接口和其相关的封装:

import requests

class GoodsApi:
    
    def __init__(self, session):
        self.session = session
        self.base_url = "https://xxx.com/api/goods"
    
    def query_good(self, name):
        url = f"{self.base_url}/{name}"
        response = self.session.get(url)
        return self._parse_response(response)
    
    def _parse_response(self, response):
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"request failed with status code {response.status_code}")

class CategoryApi:
    
    def __init__(self, session):
        self.session = session
        self.base_url = "https://xxx.com/api/category"
        
        self.goods_api = GoodsApi(session)
    
    def query_category_goods(self, category_name):
        category_info = self.query_category(category_name)
        goods_info = []
        for goods_name in category_info.get('goods'):
            good_info = self.goods_api.query_good(goods_name)
            goods_info.append(good_info)
        
        return goods_info
    
    def query_category(self, category_name):
        url = f"{self.base_url}/{category_name}"
        response = self.session.get(url)
        return self._parse_response(response)
    
    def _parse_response(self, response):
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"request failed with status code {response.status_code}")

class UserApi:
    
    def __init__(self, session):
        self.session = session
        self.base_url = "https://xxx.com/api/user"
        
        self.category_api = CategoryApi(session)
    
    def query_user_order(self, user_id):
        user_info = self.query_user(user_id)
        order_info = []
        for category_name in user_info.get('order_category'):
            order_goods = self.category_api.query_category_goods(category_name)
            order_info.extend(order_goods)
        
        return order_info
    
    def query_user(self, user_id):
        url = f"{self.base_url}/{user_id}"
        response = self.session.get(url)
        return self._parse_response(response)
    
    def _parse_response(self, response):
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"request failed with status code {response.status_code}")

class SessionApi:
    
    def __init__(self):
        self.session = requests.Session()
        self.base_url = "https://xxx.com/api"
        
        self.goods_api = GoodsApi(self.session)
        self.category_api = CategoryApi(self.session)
        self.user_api = UserApi(self.session)
    
    def login(self, user_id, password):
        url = f"{self.base_url}/login"
        data = {
            'user_id': user_id,
            'password': password
        }
        response = self.session.post(url, data=data)
        return response.json()
    
    def query_user_info(self, user_id):
        return self.user_api.query_user(user_id)
    
    def query_user_order(self, user_id):
        return self.user_api.query_user_order(user_id)
    
    def query_good_info(self, good_name):
        return self.goods_api.query_good(good_name)
    
    def query_good_price(self, good_name):
        good_info = self.goods_api.query_good(good_name)
        return good_info.get('price')

五、总结

接口自动化测试是一个日益重要的测试环节,在实现接口自动化测试的过程中,开发一个高效、可靠、易于维护的接口自动化框架非常重要。本文介绍了基础、逻辑、业务和极限改进四个方面的接口封装方法,并在代码示例中展示了如何进行接口关联和数据准备。希望本文能对您开发接口自动化框架时有所帮助。

 

【自动化测试交流】:574737577icon-default.png?t=N3I4http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=NMRVNWflxt3xkgJD_Cj1eSi6GHgTNQAw&authKey=G4Z6oltN4M9aCbBQfUODeoKPeKUsDSGmyxsSOXuwLjjN%2BBtm5ZJD3KeOsXJHwpC%2F&noverify=0&group_code=574737577接口自动化测试:

 自动化测试福利:

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis中的别名机制

在我们使用MyBatis中的select语句时&#xff0c;需要指定resultType的值&#xff0c;即查询对象的类型&#xff0c;该值是对象的完整类名&#xff0c;看起来非常的繁琐&#xff0c;因此MyBatis中有了别名机制。 使用步骤 在mybatis-config.xml文件中添加< typeAliases >…

C语言进阶——字符函数和字符串函数(上)

重点&#xff1a; 重点介绍处理字符和字符串的库函数的使用和注意事项 1、求字符串长度 strlen 2、长度不受限制的字符串函数 strcpy strcat strcmp 1、函数介绍 1.1 strlen 函数原型&#xff1a;size_t strlen (const char *str); 1、字符串以‘\0’作为结束标志&#xff0…

如何把ipa文件(iOS安装包)安装到iPhone手机上? 附方法汇总

苹果APP安装包ipa如何安装在手机上&#xff1f;很多人不知道怎么把ipa文件安装到手机上&#xff0c;这里就整理了苹果APP安装到iOS设备上的方式&#xff0c;仅供参考 苹果APP安装包ipa如何安装在手机上&#xff1f;使用过苹果手机的人应该深有感触&#xff0c;那就是苹果APP安…

登录appuploader

登录appuploader 常规使用登录方法 双击appuploader.exe 启动appuploader 点击底部的未登录&#xff0c;弹出登录框 在登录框内输入apple开发者账号 如果没有apple开发者账号&#xff0c;只是普通的apple账号&#xff0c;请勾选上未支付688 然后软件会提示输入验证码&#…

【Spring/MySQL数据库系列】数据库事务的特点与隔离级别

⭐️前面的话⭐️ 本文已经收录到《Spring框架全家桶系列》专栏&#xff0c;本文将介绍有关数据库事务的特点以及隔离级别。 &#x1f4d2;博客主页&#xff1a;未见花闻的博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4…

【C++ STL】 趣学stackqueuepriority_queue【对话情景版】

文章目录 &#x1f4cd;前言C STL 之 stack&queue基础知识及其模拟实现&#x1f4cd;容器适配器&#x1f388;什么是适配器&#xff1f;&#x1f388;STL标准库中stack和queue的底层结构&#x1f388;deque的简单介绍(了解)&#x1f4cc;deque的原理介绍&#x1f4cc;deque…

Python学习27:存款买房(A)

描述‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 你刚刚大学毕业&#xff0c;…

基于Hebb学习的深度学习方法总结

基于Hebb学习的深度学习方法总结 0 引言1 前置知识1.1 Hebb学习规则1.2 Delta学习规则 2 SoftHebb学习算法2.1 WTA(Winner Take All)2.2 SoftHebb2.3 多层Hebb网络2.4 Hebb学习的性能测评 3 参考文献 0 引言 总所周知&#xff0c;反向传播算法&#xff08;back-propagating, B…

图神经网络:(大型图的有关处理)在Pumbed数据集上动手实现图神经网络

文章说明&#xff1a; 1)参考资料&#xff1a;PYG官方文档。超链。 2)博主水平不高&#xff0c;如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。 文章目录 Pumed数据集文献阅读继续实验 Pumed数据集 导库 from torch_…

不会Elasticsearch标准查询语句,如何分析数仓数据?

1 Elasticsearch的查询语句 ES中提供了一种强大的检索数据方式,这种检索方式称之为Query DSL,Query DSL是利用Rest API传递JSON格式的请求体(Request Body)数据与ES进行交互&#xff0c;这种方式的丰富查询语法让ES检索变得更强大&#xff0c;更简洁。 1.1 查询预发 # GET /…

案例分享|地弹现象导致DCDC电源芯片工作不正常

很多读者都应该听过地弹&#xff0c;但是实际遇到的地弹的问题应该很少。本案例就是一个DCDC电源芯片的案例。 1. 问题描述 如下图1 &#xff0c;产品其中一个供电是12V转3.3V的电路&#xff0c;产品发货50K左右以后&#xff0c;大约有1%的产品无法启动&#xff0c;经过解耦定…

【C++】深入剖析C++11新特性

目录 一、C11简介 二、统一的列表初始化 1.&#xff5b;&#xff5d;初始化 2.std::initializer_list 三、声明 1.auto 2.decltype 3.nullptr 四、范围for 五、final和oberride 六、STL中一些变化 1.array 2.forward_list 3.unordered_map和unordered_set 七、右…

Python入门(十一)while循环(一)

while循环&#xff08;一&#xff09; 1.简介2.使用while循环3.让用户选择何时退出4.使用标志5.使用break退出循环6.在循环中使用continue7.避免无限循环 作者&#xff1a;xiou 1.简介 for循环用于针对集合中的每个元素都执行一个代码块&#xff0c;而while循环则不断运行&am…

虚幻引擎4利用粒子系统实现物体轨迹描绘

虚幻引擎4利用粒子系统实现物体轨迹描绘 目录 虚幻引擎4利用粒子系统实现物体轨迹描绘前言粒子系统利用粒子系统实现物体轨迹描绘创建粒子系统将粒子系统的产生位置绑定到运动物体上 小结 前言 由于在物体运动时&#xff0c;想要观察其总的运动轨迹&#xff0c;以便对其控制做…

CANoe-如何在Trace窗口显示SYN和FIN报文、同一条以太网报文在Trace窗口中的多条显示

1、如何在Trace窗口显示SYN和FIN报文 当我们使用CANoe实现TCP通信时,希望在Trace窗口直观显示报文的类型:SYN、ACK、FIN。显然Trace窗口也是支持这样的功能的。但很多时候由于一些人为的不正确的设置和配置,造成无法显示。 如果想解析出SYN报文,首先在Trace窗口选择正确的…

java注解

Target({ElementType.METHOD, ElementType.TYPE}) 注解的适用范围&#xff0c;可以用在什么地方&#xff0c;超过这个作用范围,编译的时候就会报错 值说明ElementType.METHOD用于描述方法ElementType.TYPE用于描述类、接口(包括注解类型) 或enum声明ElementType.LOCAL_VARIAB…

编程语言中,循环变量通常都用 i?你知道为什么吗?

01 前天&#xff0c;我在朋友圈发了一个问题&#xff1a; 为什么编程中&#xff0c;循环变量通常都是用 i ? 没想到&#xff0c;回复的人这么多&#xff01;要连翻好几页。 这个问题&#xff0c;有 2/3 的人回答正确&#xff0c;有少部分人知道&#xff0c;但是不太确定。 习惯…

camunda如何发布和调用rest服务接口

一、camunda如何发布rest服务接口 Camunda BPM 平台本身提供了 REST API 接口&#xff0c;可以用于管理和操作 Camunda 平台中的各种资源和数据&#xff0c;如流程定义、流程实例、任务等。因此&#xff0c;我们可以通过编写 Camunda 应用程序的方式&#xff0c;将 Camunda RE…

最流行的开源 LLM (大语言模型)整理

本文对国内外公司、科研机构等组织开源的 LLM 进行了全面的整理。 Large Language Model (LLM) 即大规模语言模型&#xff0c;是一种基于深度学习的自然语言处理模型&#xff0c;它能够学习到自然语言的语法和语义&#xff0c;从而可以生成人类可读的文本。 所谓"语言模…

基于DBSCAN密度聚类的风电-负荷场景削减方法

​目录 ​ 1 主要内容 基于密度聚类的数据预处理&#xff1a; 场景提取&#xff1a; 算法流程&#xff1a; 2 部分程序 3 程序结果 4 下载链接 1 主要内容 该程序复现文章《氢能支撑的风-燃气耦合低碳微网容量优化配置研究》第三章内容&#xff0c;实现的是基于DBSCAN…