接口自动化测试框架【AIM】

最近在做公司项目的自动化接口测试,在现有几个小框架的基础上,反复研究和实践,搭建了新的测试框架。利用业余时间,把框架总结了下来。

AIM框架介绍

AIM,是Automatic Interface Monitoring的简称,即自动化接口监测。是一种基于python unittest的自动化接口测试框架。

设计思想

框架根据python语言的特点,结合了面向对象和面向函数编程。

以高效编程为主要目的,避免为了封装而封装。轻配置,重编码。

接口测试的主要处理对象是参数。如果完全进行数据与代码的分离,就会造成变量,传参的冗余,降低编程效率。

于是从不做数据与代码分离出发,对于需要复用的参数,提取到类之外,视需要进行数据与代码的分离。

做到有的放矢。兼顾效率和复用性,迭代分离,更具实用性。

1552446647735

目录结构

1557469790003

case:测试用例

common:公共函数,全局变量

config:配置路径等

data:数据文件

result:测试结果

util:工具类

run.py:用例执行入口

run_mail.py:执行后自动发送邮件入口

case

BaseCase

所有Case的基类。

封装了requests库的post和get函数req,用于发送请求。

调用assertEqual等方法,封装了用例的断言。比如检查接口返回flag,检查接口状态200,检查值相等。

项目Case

测试系统的用例。按模块分别建立文件编写脚本。

Env.py:环境配置,包括url处理,登录对象login实例(用户名、密码),数据库对象dao实例(数据库连接)。

Public.py:公共模块。存放本系统公共的变量、函数、用例等。

common

Func.py:公共函数,比如获取时间日期,获取随机数,处理参数。

Login.py:登录模块,属于各系统通用,故放于此目录下。包括密码加密,验证码处理,强制登录。

Var.py:全局变量。比如token。

config

RelativePath.py:配置目录、文件的相对路径。

data

echarts数据存储csv文件,项目接口清单等。

result

log:日志。logging实现。支持输出到文件和打印控制台。文件暂时使用较少,主要打印控制台便于调试。

接口调用记录:输出每个测试方法调用接口的记录,包括参数、响应、耗时等。

自动化测试报告:HTMLTestRunner.py实现的html页面报告。

util

AutoCode.py:自动生成结构化测试代码。

CSV.py:csv相关函数封装。比如输出接口调用记录。

Excel.py:读取和存储excel文件。

Format.py:格式化。比如把浏览器复制的参数格式化为代码中带有缩进的json。

HTMLTestRunner.py:用于输出自动化测试报告。

Log.py:封装日志方法。

Mysql.py:数据库相关操作。

Parewise.py:结对测试。一种测试技术,后文详述。

Request.py:核心工具,封装接口发送请求。

Mail.py:发送邮件。

run.py

执行测试用例入口,可以选择执行一个或多个系统,也可以执行一个系统中一个或多个模块。

核心模块

BaseCase.req

通过requests封装的发送接口请求的方法。

定义在BaseCase类的内部。

参数说明
p将url、headers、body、method统一封装到一个json里面进行处理。
method='post'默认为post方法。接口以post居多。
jsondata='json'默认json参数。post方法的json或data,纯json使用json参数即可。对于receive_json这种dict,采用data参数。
loglevel=3默认为3。日志级别,输出请求、响应信息到控制台或接口调用记录.csv。
rtext=None一些get请求会返回html或pdf,在控制台或csv文件中影响显示,可以指定文本进行替换。

发送请求,并计算耗时:

        start = time.clock()if method == 'post':  # 关闭SSL认证if jsondata == 'json':r = self.timeoutTry("requests.post(p['url'], headers=p['headers'], json=p['body'], verify=False)", p)elif jsondata == 'data':r = self.timeoutTry("requests.post(p['url'], headers=p['headers'], data=p['body'], verify=False)", p)else:print('jsondata错误')elif method == 'get':r = self.timeoutTry("requests.get(p['url'], headers=p['headers'], params=p['body'])", p)else:print('method错误')end = time.clock()elapsed = decimal.Decimal("%.2f" % float(end - start))

其中的self.timeoutTry是为了处理响应超时,会在后续博文中介绍。

Parewise

结对测试。接口参数一般是多个,于是比较适合采用parewise进行用例设计。

parewaise的概念可以百度一下。

大概意思就是,大多数的bug都是条件的两两组合造成的,parewise就是针对两两组合的情况,设计测试用例。

算法为,如果某一组用例的组合结果,在其他组合中均出现,就删除该组用例,从而精简用例。

windows下有微软的PICT,txt文件录入参数后,命名行执行,就出来结果了。

比如参数

1552448368346

执行后结果,只有31条,精简了很多。

1552448425685

这个基本上一秒就出来结果了。

我自己参考网上算法写的,就要慢的多。

估计后面有时间了再看看能不能调优。

parewise算法:

cp = []  # 笛卡尔积
s = []  # 两两拆分
for x in eval('itertools.product' + str(tuple(param_list))):cp.append(x)s.append([i for i in itertools.combinations(x, 2)])del_row = []
s2 = copy.deepcopy(s)
for i in range(len(s)):  # 对每个进行匹配t = 0for j in range(len(s[i])):  # 判断所有同时都存在其他中 且位置相同for i2 in [x for x in range(len(s2)) if s2[x] != s[i]]:  # 其他 只比对有效flag = Falsefor j2 in range(len(s2[i2])):if s[i][j] == s2[i2][j2] and j == j2:t = t + 1flag = Truebreakif flag:breakif t == len(s[i]):del_row.append(i)s2.remove(s[i])return [cp[i] for i in range(len(cp)) if i not in del_row]

网上的例子是用的index函数。在我写过程中,发现这里有个坑。比如list中存在相同元素,就始终返回前一个匹配的索引,结果就会有问题。我就完全避免了index函数。不知道哪个是对的,目前满足使用需要,将就着用了。有点小尴尬。

Case

BaseCase断言:

    def checkFlag(self, p, r):"""预期,实际"""err = str([p['url'], p['body'], r.text])try:b = Falseif (r.json()['flag'] in [1, '1', '', None, 'statistic_by_result', 0,"0", 'struct_product', 'v_select_jz_single']or r.json()['message'] in ("暂无数据", "未查询到数据")):b = Trueself.assertEqual(True, b, msg=err)except (json.JSONDecodeError, KeyError):  # 1.返回的不是json,比如下载、404  2.无flagself.assertEqual(200, r.status_code, msg=err)

最简单的一个测试用例:

from case.PyPlatform2_0_2.Public import *class Home(BaseCase):"""首页"""def setUp(self):log(testname(self.__repr__()) + '\n')record([testname(self.__repr__())])def test(self):"""xxx"""self.req({"url": full_url("xxx"),"body": {}})

setup,输出日志。

Token

因为公司登陆用的token,跟cookie类似,保留登陆状态,避免重复登陆。

如何处理token也是框架设计的一个要点。

1557471452464

Env设置token,因为每个系统的登陆参数值都不一样。

Var.token = login.get_token()

BaseCase.req在每次请求时获取token,从而免登录。

if "headers" not in p.keys():p['headers'] = {'token': ''}p['headers']['token'] = Var.token

CSV

写文件:

if not os.path.exists(path):f = open(path, 'a', newline='')a = csv.writer(f)a.writerow(title)f.close()f = open(path, 'a', newline='')
a = csv.writer(f)
try:a.writerow(d)
except UnicodeEncodeError:d[4] = "Unicode隐藏"  # responsea.writerow(d)
f.close()if get_file_size(path) >= 50 * 1024 * 1024:  # 超过50M删除文件os.remove(path)record(title)

traceback自动生成文件名:

def _sys_name():t = str(traceback.extract_stack())b = Truefor x in os.listdir(case_dir):if x not in ["BaseCase.py", "__pycache__"]:if x in t:return x + "接口调用记录" + current_date() + ".csv"if b:print("request找不到sysname")print(t)

HTMLTestRunner

根据通用的版本,也是参考网上一些现有的美化代码,综合了一下,根据自己需求做了改造。

近20交易日测试通过率

1552449137641

加了一个echarts,把最近20交易日的测试通过率,通过折线走势图的方式展示出来。监测系统稳定性。

数据存放和读取在data目录的csv文件中。

统计表格

1552449314757

按项目进行分组统计,增加测试说明一列,按颜色区别测试结果状态,可点击查看详细描述和错误信息。

同时优化了整体的样式效果。

排序:

# 按照通过率从小到大排序
passrate_value = []
for key in passrate:if key != 'total':passrate_value.append(float(passrate[key].replace('%', '')))passrate_value.sort()

保存折线图数据:

today = datetime.datetime.now().strftime('%Y-%m-%d')
if '--' not in names:  # 跑单个系统不存if dao_is_trade_date(today):  # 非交易日不存with open(self.rct20_path, "r") as f:  # 读取数据lines = csv.reader(f)lines = list(lines)for lin in lines:lin[0] = lin[0].replace('月', '-')lin[0] = lin[0].replace('日', '')rct_data = lines# print(rct_data)nowdate = datetime.datetime.now().strftime('%m-%d')# 如果有重复日期,先删l = len(rct_data)while l != 0 and nowdate == rct_data[l - 1][0]:rct_data.pop(l - 1)l = len(rct_data)for pt in self.passrate_tl:n = pt[0]v = pt[1]row = []row.append(str(nowdate))row.append(str(n))row.append(str(v).replace('%', ''))rct_data.append(row)# 只存近20条row_20 = len(names) * 20if len(rct_data) > row_20:  # 超过20条for i in range(0, len(names)):rct_data.pop(0)with open(self.rct20_path, 'w', newline='') as f:writer = csv.writer(f)writer.writerows(rct_data)

拼接折线图数据用于展示:

while ri < len(rct_data):  # 遍历 ->s_datascan = []while ri < len(rct_data) and rct_data[ri][0] == trade_date[di]:s_data[rct_data[ri][1]].append(rct_data[ri][2])scan.append(rct_data[ri][1])ri += 1chg = list(set(names) ^ set(scan))  # 差集for c in chg:s_data[c].append('--')  # 增加/减少的项目,为'--'di += 1series = []  # 系列序列
s_names = s_data.keys()
for k in s_names:s = {}  # 单个系列s['name'] = ks['type'] = 'line'if s_data != {}:s['data'] = s_data[k]series.append(s)

这部分代码是很久之前写的了,代码应该是不够简洁、高效、规范滴,是可以优化滴。偷了懒没有重构了。

用例设计

测试类型描述
冒烟测试所有接口写单独的test,确保调用正常。
全选测试将所有参数尽可能多的全选上,调用接口。
一定程序上可以弥补结对测试的不足。
结对测试如前文所述,关注两两组合的情况。

参数值,部分采用随机数。也视需求,从数据库或其他接口获取数据。

【接口自动化测试入门】从0到1落地实施接口自动化测试框架

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

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

相关文章

xv6 文件系统(下)

〇、前言 计算机崩溃后如何恢复&#xff0c;是一个很重要的话题。对于内存中的数据无关痛痒&#xff0c;开机后重新载入就能解决问题&#xff1b;但是对于持久化存储设备&#xff0c;当你尝试修改一个文件&#xff0c;突然断电当你重新打开文件后&#xff0c;这个文件的状态是…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十五:基础数据模块相关功能实现

一、本章内容 本章使用已实现的公共组件实现系统管理中的基础数据中的验证码管理、消息管理等功能。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 3.1 B站视频地址: 基于VUE3+Layui从头搭建通用后台管理系统合集-验证码功能实现 3.2 西瓜…

社科院与新加坡新跃社科联合培养博士—我想我的人生变得精彩

既然人生的幕布已拉开&#xff0c;就一定要积极的演出&#xff0c;既然脚步已经跨出&#xff0c;风吹坎坷也不能退步&#xff0c;既然我已经把希望播在这里&#xff0c;就一定要坚持到胜利的谢幕&#xff0c;人生没有什么是为了别人做的&#xff0c;工作不是为了老板&#xff0…

79-C语言-小球降落和反弹问题

简介&#xff1a;一个球从100m高度处落下&#xff0c;每次落地后反弹回原高度一半&#xff0c;再落下&#xff0c;再反弹。问&#xff1a;它在第十次落地&#xff0c;共运动了多少米&#xff0c;第十次反弹又多高呢&#xff1f; 看代码注释即可 代码如下&#xff1a; #inclu…

Web前端-HTML(常用标签)

文章目录 1. HTML常用标签1.1 排版标签1&#xff09;标题标签h (熟记)2&#xff09;段落标签p ( 熟记)3&#xff09;水平线标签hr(认识)4&#xff09;换行标签br (熟记)5&#xff09;div 和 span标签(重点)6&#xff09;排版标签总结 1.2 标签属性1.3 图像标签img (重点)1.4 链…

MySQL进阶|MySQL中的事务(一)

文章目录 数据库事务MySQL中的存储引擎InnoDB存储引擎架构什么是事务事务的状态总结 数据库事务 MySQL 事务主要用于处理操作量大&#xff0c;复杂度高的数据。比方我想要删除一个用户&#xff08;销户&#xff09;以及这个用户的个人信息、订单信息以及其他信息&#xff0c;这…

2024年软件测试入坑指南,新人必看系列

本科非计算机专业&#xff0c;在深圳做了四年软件测试工作&#xff0c;从之前的一脸懵的点点点&#xff0c;到现在会点自动化测试&#xff0c;说一点点非计算机专业人员从事软件测试的心得体会&#xff0c;仅供参考交流。 如果你是非计算机专业&#xff0c;毕业不久&#xff0…

<JavaEE> 文件IO -- File类和文件操作

目录 一、文件的概念 二、文件系统 三、文件类型 四、使用 File 类进行文件操作 4.1 File 类中的 pathSeparator 属性 4.2 File 类构造方法 4.3 File 类常用方法 一、文件的概念 什么是文件&#xff1f; 广义上的“文件”是指抽象化的操作系统中的硬件设备和软件资源&a…

第十三章 SpringCloud Alibaba 实现 Seata--分布式事务

分布式事务基础 事务 事务指的就是一个操作单元&#xff0c;在这个操作单元中的所有操作最终要保持一致的行为&#xff0c;要么所有操作 都成功&#xff0c;要么所有的操作都被撤销。简单地说&#xff0c;事务提供一种“要么什么都不做&#xff0c;要么做全套”机制。 本地事…

RAG检索增强技术在知识库智能检索场景下的应用实践

如果你对这篇文章感兴趣&#xff0c;而且你想要了解更多关于AI领域的实战技巧&#xff0c;可以关注「技术狂潮AI」公众号。在这里&#xff0c;你可以看到最新最热的AIGC领域的干货文章和案例实战教程。 一、知识检索增强的基本概述 1.1、知识检索增强技术提出的背景 1.1.1、L…

Spring Boot学习随笔- JSP小项目-员工管理系统(验证码生成、增删改查)

学习视频&#xff1a;【编程不良人】2021年SpringBoot最新最全教程 第十章、项目开发 实现一个登录注册&#xff0c;增删改查功能的系统 10.1 项目开发流程 需求分析 分析用户主要需求 提取项目核心功能&#xff0c;根据核心功能构建页面原型 库表设计&#xff1a; 分析系统…

基于FPGA的视频接口之高速IO(CML)

简介 本章节是对于高速IO接口应用的一个扩展&#xff0c;目前扩展为CML。 CML&#xff08;电流模式逻辑-即Current Mode Logic&#xff09;。电路主要靠电流驱动&#xff0c;也是所有高速数据接口形式中最简单的一种&#xff0c;它的输入与输出的匹配集成在芯片内部&#xff0c…

mysql innodb知识记录

官方文档 官网架构图 innodb 特性 内存 buffer pool 采用优化后的LRU算法&#xff0c; 3/8 of the buffer pool is devoted to the old sublist.The midpoint of the list is the boundary where the tail of the new sublist meets the head of the old sublist.When In…

逆向登录(js逆向)

链接: aHR0cHM6Ly9zc28ubHlua2NvLmNvbS9jdXN0b21lci9sb2dpbj9jbGllbnRfaWQ9OGMxNWE2NGY2Nzk0NDY5YjhhNTlmMTBiODNjZWYzYzEmcmVkaXJlY3RfdXJpPWh0dHBzOi8vaDUubHlua2NvLmNuOjQ0My9hdXRoL21hbGwvaDUvbG9naW4mcmVzcG9uc2VfdHlwZT1jb2RlJnNjb3BlPW9wZW5pZCZzdGF0ZT0zNGQ4NGYxNmIwY…

MySQL安装——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

MySQLhttps://www.mysql.com/ 将下发的ds_db01.sql数据库文件放置mysql中 12、编写Scala代码&#xff0c;使用Spark将MySQL的ds_db01库中表user_info的全量数据抽取到Hive的ods库中表user_info。字段名称、类型不变&#xff0c;同时添加静态分区&#xff0c;分区字段为etl_da…

Win10电脑退出安全模式的两种方法

在Win10电脑中&#xff0c;大家可以点击进入系统安全模式&#xff0c;完成相对应的系统设置。但是&#xff0c;很多用户进入安全模式完成设置后&#xff0c;不知道怎么操作才能成功退出安全模式&#xff1f;接下来小编给大家分享两种简单的方法&#xff0c;帮助大家成功退出Win…

强大的数学软件 GeoGebra 多平台适用

GeoGebra 是一款教育数学软件&#xff0c;可以帮助学生和教师探索、学习和教授各种数学概念和科学领域的知识。GeoGebra 以其灵活性和强大的功能而闻名&#xff0c;它融合了几何、代数、微积分、概率、统计和其他数学领域的工具&#xff0c;以及绘图和计算功能。 功能 GeoGeb…

Java魔法解密:HashMap底层机制大揭秘

文章目录 一、 源码深度解析1.1 窥探Java集合框架中的设计思想1.2 逐行解读HashMap的源代码1.2.1 类信息1.2.2 常量属性1.2.3 变量属性1.2.4 节点信息1.2.5 构造方法1.2.6 put方法1.2.6.1 putVal方法1.2.6.2 putTreeVal方法1.2.6.3 tieBreakOrder方法1.2.6.4 treeifyBin方法1.2…

lua语法

lua语法 1.lua数据类型 lua 脚本输出乱码&#xff0c;将lua脚本改为UTF-8编码&#xff0c;并且需要DOS下修改代码页&#xff1a;CHCP 65001 即可。 基本语法 注释 print("script lua win")-- 单行注释--[[多行注释]]--标识符 类似于&#xff1a;java当中 变量、…

新建vue3项目

三种方法 一. 第一种方式 1、操作步骤&#xff1a; 创建项目目录 vue create 项目名称选择配置方式 ? Please pick a preset: #选择一个配置 Default &#xff08;[Vue 3] babel, eslint&#xff09;Default &#xff08;[Vue 2] babel, eslint&#xff09;Manually select …