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

news2024/9/20 14:56:55

 

目录

 前言:

一、接口封装与封装层级

二、接口关联和数据准备

三、接口封装极限改进

四、代码示例

五、总结


 前言:

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

本文将分享一个基于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接口自动化测试:

 自动化测试福利:

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

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

相关文章

JAVA的基本数据类型及扩大缩小转换

JAVA的8种基本类型 分为四大类:整形、浮点型、字符型、布尔型 数据类型类别大小(位)范围byte整型8-128 到 127short整型16-32768 到 32767int整型32-2147483648 到 2147483647long整型64-9223372036854775808 到 9223372036854775807float浮点型32约3.40282347e38…

房屋装修选择自装,如何寻找砌墙工人,比价并施工(砌墙阶段)

环境: 地点:杭州 装修类型:自装 面积:建面135平方 进度:砌墙阶段 问题描述: 房屋装修选择自装,如何寻找砌墙工人,比价并施工 解决方案: 一、了解砌墙相关知识 砌…

docker 安装 prometheus,grafana,node-exporter 监控工具

:https://download.csdn.net/download/qq_42208305/87792827 加载离线镜像 : 监控端安装: docker load -i prometheus.tar docker load -i grafana.tar 被监控端安装: docker load -i node-expo…

类加载器与模块化系统

1 类加载器 “类加载器”是实现应用程序自己决定如何去获取所需的类这个动作的代码。 1.1 类与类加载器 比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义。否则,即使这两个类来源同一个Class文件,被同一个J…

智慧型档案馆十防一体化安全管控平台所需要的主要产品

档案八防十防常用的十款设备 序号 名称 1 温湿度传感器 2 空气质量云测仪 3 恒湿净化一体机 4 健康防护一体机 5 综合智能触摸一体化区域控制器 6 空调红外学习控制模块 7 漏水检测控制器及感应线 8 数字烟雾传感器 9 红外防盗传感器 10 系统软件平台 附…

无脑006——mmrotate框架下复现RTMDet-R

必须用mmrotate才有hrsc的程序 1 安装环境: Linux RTX 3090 nvcc --version cuda 11.3 pytorch 1.11.0 conda install pytorch1.11.0 torchvision0.12.0 torchaudio0.11.0 cudatoolkit11.3 -c pytorch测试pytorch是否安装成功: >>> torch.…

深入浅出PyTorch数据读取机制

熟悉深度学习的小伙伴一定都知道:深度学习模型训练主要由数据、模型、损失函数、优化器以及迭代训练五个模块组成。如下图所示,Pytorch数据读取机制则是数据模块中的主要分支。 Pytorch数据读取是通过​​Dataset​​​​​Dataloader​​的方式完成。其…

SOME/IP中间件通信流程

本文根据文章《CAPL如何实现SOME/IP协议通信:SomeIP_IL.dll函数篇(超两万字详解)》内容,抽取总结出SOME/IP通信流程,正不正确的另说,目的是为了加深对SOME/IP中间件的理解。 首先,不管是消费方consumer,还是提供方provider,都有自己的someip中间件。本质上,它是一个…

vue3 cesium datav 可视化大屏

目录 0. 预览效果 1. 代码库包 2. 技术点 3. 一些注意事项(配置参数) 4. 相关代码详情 0. 预览效果 包含的功能: ① 地球按照一定速度自转 ② 修改加载的geojson面样式 ③ 添加 文字 标注! 1. 代码库包 直接采用vue-cli5 创建…

MySql从入门到精通

MySql介绍 MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。 什么是数据库 数据库(Database)是按照数据结构来组织、存储…

oracle 闪回恢复

oracle 闪回恢复 闪回恢复区主要通过3个初始化参数来设置和管理: db_recovery_file_dest:指定闪回恢复区的位置 db_recovery_file_dest_size:指定闪回恢复区的可用空间大小 db_flashback_retention_target:指定数据库可以回退的时…

年近30 ,无情被辞,想给划水的兄弟提个醒

前几天,一个认识了好几年在大厂工作的程序员朋友,年近30了,却被大厂以“人员优化”的名义无情被辞,据他说,有一个月散伙饭都吃了好几顿…… 在很多企业,都有KPI考核,然后在此基础上还会弄个“末…

讲的太好了!!!————————Idea中的VM Options、Program Arguments、Environment Variable全解析

参数使用方式示例代码获取方式VM Options必须以 -D 、 -X 、 -XX 开头,每个参数用空格隔开 ,使用最多的就是 -Dkeyvalue-Dvm.keyVmKey -Dvm.key2VmKey2String key System.getProperty(“vm.key”); Program Arguments为我们传入main方法的字符串数组arg…

10-03 单元化架构设计

设计原则 透明 对开发者透明 在做实现时,不依赖于单元划分和部署对组件透明 在组件运行时,不感知其承载单元对数据透明 数据库并不知道为哪个单元提供服务 业务可分片 系统业务复杂度足够高系统可以按照某一维度进行切分系统数据必须可以被区分 业务…

【网络】交换机基本原理与配置

目录 🍁交换机工作原理 🍁交换机接口的双工模式 🍁交换机命令行模式 🍁交换机常见命令 🧧帮助命令 🧧常用命令介绍 🍁交换机的基本配置 🧧配置接口的双工模式及速率 🦐博…

knife4j生产环境资源屏蔽

问题描述 knife4j是目前比较主流的自动API文档生成工具,在生产环境使用的过程中,我们一般会屏蔽或者去除Swagger的文档口径,防止接口信息泄露,保证系统安全。 但是最近在开发过程中使用knife4j-spring-boot-starter 3.0.2过程中&…

dolphinscheduler使用impala shell执行sql

目录 一、背景 二、方法 1.impala shell -f 文件名 2.impala shell -q sql 一、背景 因为dolphinscheduler工具sql组件不支持impala数据源,只能折衷方法通过shell来执行impala sql。 二、方法 1.impala shell -f 文件名 操作步骤: 1).【资源中心】…

受邀参加【第七届】中国客户服务节

在AI浪潮的推动下,客户服务“智能化”是企业高质量发展的重要途径之一,目前人工智能、大数据、云计算等技术已广泛应用于全行业的客户服务场景中,一个全面、完善、稳定的智能通讯服务平台可助力实现企业智能化应用转型和升级。 讯鸿网络作为国…

嘉立创EDA原理图封装画错了怎么办

摘要:本文以贴片电阻封装由1206修改为0805为例,介绍一下封装修改的一种方法。 1.问题描述 设计原理图的时候,误将封装设计成为1206了,现在想把它改为0805封装。 2.修改封装的步骤 首先在原理图中,修改对应的电阻器件…

Flutter 3.10 适配之单例 Window 弃用,一起来了解 View.of 和 PlatformDispatcher

Flutter 3.10 发布之后,大家可能注意到,在它的 release note 里提了一句: Window singleton 相关将被弃用,并且这个改动是为了支持未来多窗口的相关实现。 所以这是一个为了支持多窗口的相关改进,多窗口更多是在 PC 场…