接口测试返回参数的自动化对比!
引言
在现代软件开发过程中,接口测试是验证系统功能正确性和稳定性的核心环节。接口返回参数的对比不仅是确保接口功能实现的手段,也是测试过程中常见且重要的任务。为了提高对比的效率和准确性,我们可以通过自动化手段实现这一过程。本文将介绍接口测试返回参数自动化对比的原理,展示如何使用 Python 和 MySQL 实现对比功能,并提供最佳实践的建议,帮助读者在实际项目中应用这些技术。
自动化对比的原理
接口测试返回参数的自动化对比涉及以下几个步骤:
-
提取和存储预期结果:在测试用例设计阶段,定义接口调用的预期返回结果,并将其存储在文件或数据库中。
-
执行接口调用:通过自动化测试脚本执行接口调用,获取实际的返回结果。
-
结果比对:将实际返回的结果与预期结果进行比对,以确认接口是否满足需求。
自动化对比的工作流程
-
准备测试数据:包括请求参数和预期返回结果。
-
执行测试用例:发送请求并接收响应。
-
对比实际返回的结果和预期结果:通过编写自动化脚本对比返回的参数。
-
记录对比结果:将对比结果存储到数据库中,并生成测试报告。
-
数据清理:在测试完成后对数据进行清理以维护数据库的健康状态。
数据库设计与实现
为了实现自动化对比,我们选择 MySQL 数据库来存储测试执行信息和对比结果。以下是数据库设计方案及其实现细节。
数据库表设计
1. 测试执行表
存储每次测试执行的信息。
CREATE TABLE test_execution (execution_id VARCHAR(36) PRIMARY KEY,test_case_id INT NOT NULL,execution_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,status VARCHAR(10) NOT NULL
);
2. 接口调用表
存储每次接口调用的信息。
CREATE TABLE api_call (call_id VARCHAR(36) PRIMARY KEY,execution_id VARCHAR(36),api_endpoint VARCHAR(255) NOT NULL,request_params JSON,response_data JSON,compare_result VARCHAR(10),FOREIGN KEY (execution_id) REFERENCES test_execution(execution_id)
);
3. 对比结果表
存储每次对比的详细信息。
CREATE TABLE compare_result (compare_id VARCHAR(36) PRIMARY KEY,call_id VARCHAR(36),field_name VARCHAR(255),expected_value TEXT,actual_value TEXT,match_result VARCHAR(10),FOREIGN KEY (call_id) REFERENCES api_call(call_id)
);
数据库操作示例
以下是插入测试执行记录、接口调用记录和对比结果记录的代码示例:
import mysql.connector
from uuid import uuid4# 数据库上下文管理器
class Database:def __enter__(self):self.connection = mysql.connector.connect(host="localhost",user="root",password="password",database="test_db")self.cursor = self.connection.cursor()return selfdef __exit__(self, exc_type, exc_value, traceback):self.connection.commit()self.cursor.close()self.connection.close()# 插入测试执行记录
def insert_test_execution(test_case_id):execution_id = str(uuid4())with Database() as db:db.cursor.execute("INSERT INTO test_execution (execution_id, test_case_id, status) VALUES (%s, %s, %s)",(execution_id, test_case_id, 'running'))return execution_id# 插入接口调用记录
def insert_api_call(execution_id, api_endpoint, request_params, response_data, compare_result):call_id = str(uuid4())with Database() as db:db.cursor.execute("INSERT INTO api_call (call_id, execution_id, api_endpoint, request_params, response_data, compare_result) VALUES (%s, %s, %s, %s, %s, %s)",(call_id, execution_id, api_endpoint, json.dumps(request_params), json.dumps(response_data), compare_result))return call_id# 插入对比结果记录
def insert_compare_result(call_id, field_name, expected_value, actual_value, match_result):compare_id = str(uuid4())with Database() as db:db.cursor.execute("INSERT INTO compare_result (compare_id, call_id, field_name, expected_value, actual_value, match_result) VALUES (%s, %s, %s, %s, %s, %s)",(compare_id, call_id, field_name, expected_value, actual_value, match_result))
动态参数的过滤
在接口测试中,动态参数(如时间戳、随机数等)可能会导致对比结果的不一致。为了提高对比的准确性,需要在对比过程中对这些动态参数进行过滤。
动态参数过滤的实现
以下是动态参数过滤的示例代码,过滤掉返回结果中的动态字段:
import requests
import json# 动态参数过滤函数
def filter_dynamic_params(response_data: dict, exclude_keys: list) -> dict:"""过滤动态参数,排除不需要对比的字段。"""return {k: v for k, v in response_data.items() if k not in exclude_keys}# 动态参数列表
dynamic_params = ['timestamp', 'token', 'session_id']# 执行接口调用并对比结果
def call_and_compare(execution_id, url, params, expected_response):response = requests.post(url, json=params)actual_response = response.json()filtered_response = filter_dynamic_params(actual_response, dynamic_params)filtered_expected_response = filter_dynamic_params(expected_response, dynamic_params)compare_result = 'match' if filtered_expected_response == filtered_response else 'mismatch'call_id = insert_api_call(execution_id, url, params, filtered_response, compare_result)for key in filtered_expected_response:if key in filtered_response:match_result = 'match' if filtered_expected_response[key] == filtered_response[key] else 'mismatch'insert_compare_result(call_id, key, filtered_expected_response[key], filtered_response[key], match_result)# 测试用例
def test_interface():execution_id = insert_test_execution(1)url = "http://api.example.com/login"params = {"username": "test", "password": "test"}expected_response = {"status": "success", "timestamp": "ignore"}call_and_compare(execution_id, url, params, expected_response)# 更新测试执行状态with Database() as db:db.cursor.execute("UPDATE test_execution SET status = %s WHERE execution_id = %s", ('completed', execution_id))if __name__ == "__main__":test_interface()
集成对比结果的报告内容
在测试执行完成后,我们可以生成一个对比结果报告,以展示测试的执行情况和结果。
生成报告的代码示例
from jinja2 import Template# 生成对比结果报告
def generate_report(execution_id):with Database() as db:db.cursor.execute("""SELECT a.api_endpoint, a.request_params, a.response_data, a.compare_result, c.field_name, c.expected_value, c.actual_value, c.match_resultFROM api_call aJOIN compare_result c ON a.call_id = c.call_idWHERE a.execution_id = %s""", (execution_id,))results = db.cursor.fetchall()# Jinja2 模板template_str = """<!DOCTYPE html><html><head><title>测试对比结果报告</title></head><body><h1>测试对比结果报告</h1><p><strong>测试执行ID:</strong>{{ execution_id }}</p><table border="1"><tr><th>接口地址</th><th>请求参数</th><th>返回数据</th><th>对比结果</th><th>字段名称</th><th>预期值</th><th>实际值</th><th>匹配结果</th></tr>{% for row in results %}<tr><td>{{ row.api_endpoint }}</td><td>{{ row.request_params }}</td><td>{{ row.response_data }}</td><td>{{ row.compare_result }}</td><td>{{ row.field_name }}</td><td>{{ row.expected_value }}</td><td>{{ row.actual_value }}</td><td>{{ row.match_result }}</td></tr>{% endfor %}</table></body></html>"""template = Template(template_str)html_report = template.render(execution_id=execution_id, results=results)# 保存报告到文件with open(f'report_{execution_id}.html', 'w') as f:f.write(html_report)
对比数据的清理
测试完成后,需要对比数据进行清理,以保持数据库的健康状态。以下是手动和自动数据清理的示例代码。
手动清理数据
def manual_cleanup(execution_id):with Database() as db:db.cursor.execute("DELETE FROM compare_result WHERE call_id IN (SELECT call_id FROM api_call WHERE execution_id = %s)", (execution_id,))db.cursor.execute("DELETE FROM api_call WHERE execution_id = %s", (execution_id,))db.cursor.execute("DELETE FROM test_execution WHERE execution_id = %s", (execution_id,))
自动清理数据
import schedule
import time# 自动清理任务
def auto_cleanup():with Database() as db:db.cursor.execute("""DELETE FROM compare_result WHERE compare_id IN (SELECT compare_id FROM compare_resultWHERE compare_id NOT IN (SELECT compare_id FROM api_call WHERE execution_id IN (SELECT execution_id FROM test_execution WHERE status = 'completed')))""")db.cursor.execute("""DELETE FROM api_call WHERE call_id IN (SELECT call_id FROM api_callWHERE call_id NOT IN (SELECT call_id FROM compare_result))""")db.cursor.execute("""DELETE FROM test_execution WHERE status = 'completed' AND execution_id NOT IN (SELECT execution_id FROM api_call)""")# 设置定时任务
schedule.every().day.at("00:00").do(auto_cleanup)while True:schedule.run_pending()time.sleep(1)
结论
在本文中,我们详细探讨了接口测试返回参数的自动化对比方法,包括动态参数的过滤、对比结果的报告生成以及对比数据的清理。通过合理的工具和技术手段,可以显著提高接口测试的效率和效果。希望本文提供的实践经验和代码示例能帮助从事接口测试的技术人员在实际项目中更好地应用自动化对比技术,提高测试的质量和效率。
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!

软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。


相关文章:
接口测试返回参数的自动化对比!
引言 在现代软件开发过程中,接口测试是验证系统功能正确性和稳定性的核心环节。接口返回参数的对比不仅是确保接口功能实现的手段,也是测试过程中常见且重要的任务。为了提高对比的效率和准确性,我们可以通过自动化手段实现这一过程。本文将…...
React基础学习-Day02
React基础学习-Day02 1.受控表单绑定 在 React 中,受控表单(controlled form)是一种通过 React 组件状态(state)来管理表单元素值的方式。使用受控表单,可以将表单元素的值与 React 组件的状态保持同步&a…...
切换网页visibilitychange,的升级版实现
目录 1 需求场景 2 用到的技术 3 日常检测方法 4 一个有意思的场景 5 升级版实现一 5.1 新建 /utils/browser.js 5.2 项目业务组件中使用 6 升级版实现二 6.1 安装js-tool-big-box工具库 6.2 引入 browserBox 对象 6.3 以控制累加定时器为例 6.4 查看定时器效果 1…...
基于pytesseract的OCR图片识别
简介 pytesseract是基于谷歌的tesseract的OCR包,支持识别一些简单的数字、字母、中文。 安装 安装引擎 下载地址:https://digi.bib.uni-mannheim.de/tesseract/ 一般是Windows 64位系统最新版: 如果要识别中文,注意选中中文…...
Docker_指令篇
Docker 的常用指令 1. 启动docker systemctl start docker2. 关闭docker systemctl stop docker3. 重启docker systemctl restart docker4. 设置自启动 systemctl enable docker5. 查看运行状态 systemctl status docker6. 查看帮助命令 docker pull --help7. 查看镜像 …...
HAL_UART_Transmit()函数用法
HAL_UART_Transmit函数用法 HAL_UART_Transmit()是 HAL 库中的一个函数,用于向指定的串口发送数据。它的函数原型如下: HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)其中各参数的含…...
OpenCV一个简单的摄像头调用与关闭
在使用OpenCV(Open Source Computer Vision Library)进行摄像头调用与关闭时,通常使用cv2.VideoCapture()函数来调用摄像头,并通过适当的方式关闭它。 调用摄像头 首先,需要导入OpenCV库(通常简写为cv2&a…...
深度学习5 神经网络
生物神经网络是指人的大脑,这是人工神经网络的技术原型。根据生物神经网络的原理,人们用计算机复现了简化的神经网络。当然,人工神经网络是机器学习的一大分支。 1.基本组成 1.1神 经 元 神经元是神经网络的基本组成。激活函数又称作激励函…...
js中! 、!!、?.、??、??=的用法及使用场景
js中! 、 !. 、!、?.、.?、??、??的用法及使用场景 !!!?.??????、?? 区别 !. (ts)注意 ! (非空断言符号) 用于取反一个布尔值或将一个值转换为布尔类型并取反 const a true; const b false; const value !a; // false const value !…...
嵌入式面试高频八股文面试题及参考答案
目录 什么是嵌入式系统?请简要描述其特点。 请解释实时操作系统(RTOS)的概念。 请列举几种常见的嵌入式操作系统。 请解释中断、异常和竞态条件在嵌入式系统中的作用。 什么是死锁?请举例说明如何避免死锁的发生。 请解释进程和线程的区别。 请解释同步和互斥的概念…...
前端练习小项目——方向感应名片
前言:在学习完HTML和CSS之后,我们就可以开始做一些小项目了,本篇文章所讲的小项目为——方向感应名片 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 在开始学习之前,先让我们看一…...
【Vim】为什么程序员喜欢用 Vim
1. Vim介绍 Vim是一款高度可配置的文本编辑器,它被设计成作为一个工具,可以非常高效地进行文本编辑工作。以下是关于Vim的一些基本介绍: 历史:Vim 是 Vi 文本编辑器的改进版,最初由布莱姆米勒(Bram Moole…...
stm32h743 NetXduo 实现http server CubeIDE+CubeMX
在这边要设置mpu的大小,要用到http server,mpu得设置的大一些 我是这么设置的,做一个参考 同样,在FLASH.ld里面也要对应修改,SECTIONS里增加.tcp_sec和 .nx_data两个区,我们用ram_d2区域去做网络,这个就是对应每个数据在d2区域的起点。 在CubeMX里,需要用到filex、dhc…...
ubuntu服务器部署vue springboot前后端分离项目
上传构建好的vue前端文件 vscode构建vue项目,会生成dist目录 npm run build在服务器root目录新建/projects/www目录,把dist目录下的所有文件,上传到此目录中 上传ssl证书 上传ssl证书到/projects目录中 配置nginx 编辑 /etc/nginx/site…...
【python】pandas报错:UnicodeDecodeError详细分析,解决方案以及如何避免
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...
FlinkModule加载HiveModule异常
HiveModule这个模块加载不出来 加在不出来这个模块,网上查说是要加下面这个依赖 <dependency><groupId>org.apache.flink</groupId><artifactId>flink-connector-hive_${scala.binary.version}</artifactId><version>${flink.…...
计算机硬件---如何更新自己电脑的BLOS
1找官网 例如“我使用的是HP(惠普)品牌的电脑”我只需要在浏览器上搜索“惠普官网”或“惠普-blos更新” 就可以看到,来自官网中更新blos的信息 2.有些品牌要查序列号该怎么办呢? 有许多方法可以查询,例如…...
AI算法17-贝叶斯岭回归算法Bayesian Ridge Regression | BRR
贝叶斯岭回归算法简介 贝叶斯岭回归(Bayesian Ridge Regression)是一种回归分析方法,它结合了岭回归(Ridge Regression)的正则化特性和贝叶斯统计的推断能力。这种方法在处理具有大量特征的数据集时特别有用ÿ…...
唯众物联网综合实训台 物联网实验室建设方案
物联网综合实训装置 物联网工程应用综合实训台是我公司针对职业院校物联网行业综合技能型人才培养,综合运用传感器技术、RFID技术、接口控制技术、无线传感网技术、Android应用开发等,配合实训台上的433M无线通信设备、ZigBee节点、射频设备、控制设备、…...
深入浅出 Vue.js:从基础到进阶的全面总结
深入浅出 Vue.js:从基础到进阶的全面总结 Vue.js 是一个用于构建用户界面的渐进式框架。它不仅易于上手,还能通过其强大的生态系统支持复杂的应用开发。本文将从基础到进阶,全面总结 Vue.js 的核心概念、常用技术和最佳实践,并提…...
GLM-OCR效果展示:复杂版式、表格、公式识别案例全解析
GLM-OCR效果展示:复杂版式、表格、公式识别案例全解析 1. 专业级OCR的新标杆 在文档数字化处理领域,传统OCR技术往往在遇到复杂版式、数学公式或嵌套表格时束手无策。GLM-OCR的出现彻底改变了这一局面——这个轻量级多模态OCR模型在权威文档解析基准测…...
MOSFET栅极电阻选型实战:从波形分析到最佳阻值确定(附IRF540实测数据)
MOSFET栅极电阻选型实战:从波形分析到最佳阻值确定(附IRF540实测数据) 在电力电子设计中,MOSFET的栅极电阻选型往往被工程师视为"小问题",但实际调试中却可能成为影响系统稳定性的关键因素。记得去年参与一款…...
BGE-Reranker-v2-m3性能实测:毫秒级响应的RAG优化方案
BGE-Reranker-v2-m3性能实测:毫秒级响应的RAG优化方案 1. 引言:RAG系统的精准度挑战 在实际的RAG(检索增强生成)应用场景中,很多开发者都会遇到这样的困境:明明检索到了一堆看似相关的文档,但…...
零基础小白必看!PyTorch 2.6 镜像一键部署,开箱即用
零基础小白必看!PyTorch 2.6 镜像一键部署,开箱即用 1. 为什么选择PyTorch 2.6镜像? PyTorch作为当前最流行的深度学习框架之一,其2.6版本带来了多项性能优化和新特性。但对于初学者来说,手动配置PyTorch环境往往是个…...
Qwen3-ASR性能优化:基于CNN的语音特征提取技术
Qwen3-ASR性能优化:基于CNN的语音特征提取技术 语音识别技术发展到今天,已经不再是实验室里的新奇玩具,而是我们日常生活中随处可见的实用工具。从手机语音助手到会议记录软件,从智能家居控制到车载语音交互,语音识别…...
OpenClaw自然语言编程:千问3.5-27B理解模糊需求并执行
OpenClaw自然语言编程:千问3.5-27B理解模糊需求并执行 1. 当AI学会追问:模糊指令的自动化实践 上周日晚上11点,我盯着电脑里散落的387张旅行照片发呆——它们杂乱地堆在Downloads文件夹里,有手机直出的JPG、相机导入的RAW、截图…...
Linux实现简易版Shell的代码详解
一、程序流程分析我们日常使用Bash时,通过输入命令执行相应的操作,比如:那么,Bash是如何进行工作的呢?观察一下,就会发现,首先Bash会打印命令行提示符,包括当前用户、主机名以及路径…...
二次元助手:OpenClaw+Phi-3-mini-128k-instruct自动整理动漫资源库
二次元助手:OpenClawPhi-3-mini-128k-instruct自动整理动漫资源库 1. 为什么需要自动化整理动漫资源库 作为一个资深动漫爱好者,我的下载文件夹常年处于混沌状态。新番、老番、剧场版混杂在一起,文件名千奇百怪——有的带字幕组前缀&#x…...
C++编程进阶:探索内建数学函数与C++20的<numbers>头文件
C编程进阶:探索内建数学函数与C20的头文件 在C编程的世界里,数学运算无处不在,无论是游戏开发中的物理模拟、图形处理,还是数据分析中的复杂计算,数学函数都是不可或缺的工具。随着C标准的不断演进,C20引入…...
OpenClaw省钱全攻略,掌握这5招,每月少花几百块冤枉钱
手把手教你一键部署OpenClaw,连接微信、QQ、飞书、钉钉等,1分钟全搞定! 刚把OpenClaw折腾好,你可能正沉浸在AI秒回代码、自动理任务的神奇体验里,心里直呼过瘾。可还没等新鲜劲过去,一翻后台账单ÿ…...
