接口自动化测试,一键快速校验接口返回值全部字段

news2025/2/24 13:31:41

目录

前言:

一、认识一下,DeepDiff 介绍

主要组成部分:

二、DeepDiff 使用

2.1 案例一:比较两个 JSON

2.2 案例二:比较接口响应

2.3 案例三:正则搜索匹配

三、最后一个小技巧:DeepDiff 黑名单

四、小结


前言:

在接口自动化测试中,快速校验接口返回值的全部字段是一个重要的任务。通过一键快速校验,可以有效地验证接口的返回数据是否符合预期,并及时发现潜在的问题。

今天,我们先来聊聊,如何借助现有的第三方库来解决: 快速校验 API 接口返回的全部字段。由于当今大部分接口都是基于 Restful API,后续我介绍中,我们假设接口响应体格式以 JSON 为例。

要满足上面的实现需求,第三方库方案有很多,比如常见的就有:deepdiffdifflibjson-diffjson_tools 等,这些三方库之间,都有各自侧重点,本篇文章,重点介绍:如何借助 DeepDiff 库来解决快速校验接口返回字段的问题

一、认识一下,DeepDiff 介绍

Deepdiff模块常用来校验两个对象是否一致,并找出其中差异之处。其中提供了三个类,DeepDiff,DeepSearch 和 DeepHash,官网地址:DeepDiff OLD 4.0.7 documentation! — DeepDiff 4.0.7 documentation ,当前最新版本为:V5.5.0

主要组成部分:

  • DeepDiff:比较两个对象,对象可以是字段、字符串等可迭代的对象,针对对象的深层差异,递归查找所有更改。

  • DeepSearch:在对象中搜索其他对象

  • DeepHash:根据对象的内容进行哈希处理

DeepDiff 的初衷是用来找出不同数据的差别,可以比较JSONXML文本类的,也可以比较图片,在使用了一下之后,其实我们完全可以直接使用它作为测试的断言,这也是从另一个思考角度提供了一种全新的校验思路

二、DeepDiff 使用

当你看完上述的介绍,相信还是一脸懵,不知如何下手,接下来,就通过几个案例来进一步感受一下Deepdiff的功能和作用。

使用之前,先安装:

pip install deepdiff

2.1 案例一:比较两个 JSON

利用 Deepdiff 比较 JSON 的差异:

import pytest
import requests
import pprint
from deepdiff import DeepDiff

class TestDemo(object):

    def test_case_01(self):
        a = {"Object": {
            "code": "0",
            "message": "success"
        },
            "code": "0",
            "message": "success"
        }

        b = {"Object": {
            "code": "0",
            "message": "failure"
        },
            "message": "success",
            "timestamp": "1614301293"
        }

        pprint.pprint(DeepDiff(a, b))

上述案例,作用是比较 a 和 b 两者的差异,result 差异的输出结果是:

.{'dictionary_item_added': [root['timestamp']],
 'dictionary_item_removed': [root['code']],
 'values_changed': {"root['Object']['message']": {'new_value': 'failure',
                                                  'old_value': 'success'}}}

上述输出结果中,实际上根据这个返回的 json 获取所有的差别。主要是对比对象之间的值、类型前后之间的变化以及删除的或者增加的情况 key 进行了结果输出。

主要包含以下四种情况:

  • 1、type_changes:类型改变的 key
  • 2、values_changed:值发生变化的 key
  • 3、dictionary_item_added:字典 key 添加
  • 4、dictionary_item_removed:字段 key 删除

2.2 案例二:比较接口响应

有了案例一的基础,进一步,我们将本地定义写死的变量值改成采取调用接口的方式(更符合实际接口测试),通过发起请求,获取响应、并结合 Deepdiff 来断言使用。

核心思路:先定义预期的响应结构体(意味着,你得事先知道你期望的结果是什么),再根据实际返回的结构体两者通过Deepdiff进行自动比较。

import pytest
import requests
import pprint
from deepdiff import DeepDiff


class TestDemo(object):

    def setup_class(self):
        self.response = requests.get('http://www.httpbin.org/json').json()

    def test_case_02(self):
        expected_reps = {'slideshow': {'author': 'Yours Truly', 'date': 'date of publication',
                                       'slides': [{'title': 'Wake up to WonderWidgets!', 'type': 'all'}, {
                                           'items': ['Why <em>WonderWidgets</em> are great',
                                                     'Who <em>buys</em> WonderWidgets'], 'title': 'Overview',
                                           'type': 'all'}], 'title': 'Sample Slide Show'}}
        pprint.pprint(DeepDiff(expected_reps, self.response))

由于实际返回的结构体和预期定义待校验的结构体数据完全一样,因此上述代码输出结果为:{},即两者没有差异。(也意味着实际和预期结果一致)

在此基础上,如果我们把上述expected_reps预期结构体中的authorYours Truly修改为Yours,再执行一次,则输出的结果为:

{'values_changed': {"root['slideshow']['author']": {'new_value': 'Yours Truly',
                                                    'old_value': 'Yours'}}}

从上述的输出结果中,我们可以很明显的获取到三个讯息:

  • 接口返回的结构体中有值发生了改变,通过values_changed标识出来了
  • 明确指出具体哪个字段的值发生改变了,如root['slideshow']['author']
  • 改变具体的内容,如实际返回值为Yours Truly,而预期值为Yours

看完了这个,相信此时的你,对 Deepdiff 在接口测试中的使用,已经有了一些感觉了。但接着你肯定会提出疑问,有些接口返回的值,并不是固定的,那比如校验呢。比如某个时间戳字段,每次调用接口时,返回字段的值都是不一样,针对这类只知道数据规则,但数据本身的值一开始是无法确定的,又该如何结合 Deepdiff 来使用呢?别急,再接着往下看。

2.3 案例三:正则搜索匹配

要解决上述的问题,可以利用DeepSearch中的正则搜索匹配功能,如果你的接口返回,是一个很深的嵌套结构对象,然后你想校验查找指定的元素(key 和 value 都行)是否存在,那么 Deep Search 将是个好选择。

使用前,需要先导入from deepdiff import grep,示例源码如下:

def test_case_03(self):
    datas = {"mikezhou": "狂师", "age":18, "city": "china", "info": {"author": {"tag": "mikezhou"}}}
    reuslt = datas | grep("mike*",use_regexp=True)
    print(reuslt)

比如想校验有没有以 mike 开头字段或值在返回的结构体中,指定元素存在则返回它的路径;不存在则返回一个空字典。上述输出结果如下:

.{'matched_paths': ["root['mikezhou']"], 'matched_values': ["root['info']['author']['tag']"]}

上述示例虽简单,但如果你足够聪明,相信应该已经能从中 Get 核心思路了:针对一些动态事先无法预料的值,可以通过借助正则表达式来匹配校验,具体如何校验,取决于你的正则表达式如何描述。

三、最后一个小技巧:DeepDiff 黑名单

在实际做接口测试断言时,有时对象顺序不一样,但是实际情况两个值还是一样的,或者是针对全量字段校验时,想跳过一些特殊的字段校验(类似黑名单一样,将不需要校验的字段,明确指出),为了解决这类问题,Deepdiff 也提供了相信的参数,只需要在比较的时候加入:

  • ignore order(忽略排序)
  • ignore string case(忽略大小写)
  • exclude_paths字段黑名单排除参数即可,原型如下:
result = DeepDiff(result, expected, view='tree',ignore_order=True,ignore_string_case=True)

示例:

def test_case_05(self):
    expected_reps = {"datas": {
        "code": "200",
        "message": "success"
    },
        "code": "201",
        "message": "success"
    }

    actual_reps = {"datas": {
        "code": "201",
        "message": "failure"
    },
        "message": "Success",
        "timestamp": "1614301293"
    }

    pprint.pprint(DeepDiff(expected_reps, actual_reps, ignore_order=True,ignore_string_case=True,exclude_paths={"root['timestamp']"}))

上述示例代码,忽略了排序规则、大小写问题,并且指定排除timestamp字段校验。具体的输出结果如下:

{'dictionary_item_removed': [root['code']],
 'values_changed': {"root['datas']['code']": {'new_value': '201',
                                              'old_value': '200'},
                    "root['datas']['message']": {'new_value': 'failure',
                                                 'old_value': 'success'},
                    "root['message']": {'new_value': 'Success',
                                        'old_value': 'success'}}}

四、小结

通过上述的案例介绍,相信你对DeepDiff的使用有了一个基本认识。在接口自动化测试中,小结一下,使用 DeepDiff 的好处有:

  1. 接口测试的时候,可以直接利用预期结构体(或者称之为接口契约)与实际返回的结构体(字段、值)进行自动比较,来确定是不是一样,可以少写很多代码。
  2. 数据库数据比较的时候也是一样可以,使用 SQL 查出结果之后,直接变成 JSON 就可以和期望的 JSON 对比了。

  作为一位过来人也是希望大家少走一些弯路

在这里我给大家分享一些自动化测试前进之路的必须品,希望能对你带来帮助。

(WEB自动化测试、app自动化测试、接口自动化测试、持续集成、自动化测试开发、大厂面试真题、简历模板等等)

相信能使你更好的进步!

点击下方小卡片

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

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

相关文章

【代码随想录 | Leetcode | 第二天】数组 | 双指针法 | 相向双指针 | 27

前言 欢迎来到小K的Leetcode|代码随想录|专题化专栏&#xff0c;今天将为大家带来双指针法和相向双指针的分享✨ 目录 前言27. 移除元素 27. 移除元素 ✨题目链接点这里 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于val的元素&#xff0c;并返回…

keep-alive和router-view配合使用缓存整个路由页面以及路由切换

实现内容&#xff1a;通过vue实现&#xff0c;在页面有侧边栏动态来展示当前页面流程&#xff0c;右边进行页面的切换&#xff0c;左右两边都是组件&#xff0c;但是A/B/C组件的切换是通过keep-alive搭配router-view实现的&#xff0c;首先在当前文件中创建五个文件&#xff1a…

Linux系统编程(传统信号和实时信号)

文章目录 前言一、传统信号和实时信号概念二、重要函数介绍三、实时信号和传统信号被处理的次数总结 前言 本篇文章我们来讲解传统信号和实时信号&#xff0c;这里我们将从实际应用给大家讲解。 一、传统信号和实时信号概念 传统信号&#xff08;Traditional Signals&#x…

spring boot学习第一篇:spring boot 1.5.x版本启动接口服务

1、pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.…

华为云出品《IDEA-Plugin-开发手册》电子书——学完即会场景设计

小智又来给各位开发者送书啦&#xff01; 助力各位开发者们提升技能 海量案例串联 IEDA Plugin 插件开发技能 重实践与验证帮助避免踩坑 学完就可自己完成一些场景设计和开发 适合有一定编程基础&#xff0c;1年以上经验的开发者 适合对IDEA Plugin有学习需求或想拓展业务…

出海企业系列风险分析--网站需要验证码吗?

最近接待了几位从discuz来的用户&#xff0c;说是想要给自己海外的网站安装验证码&#xff0c;但是discuz境外服务器还要解析安装中心的DNS到境外服务器上&#xff0c;所以基于discuz建站的不好之处就在这里。 而且我们还讨论到一个问题&#xff0c;海外的网站&#xff0c;需要…

【线程概念和线程控制】

目录 1 :peach:线程概念 :peach:1.1 :apple:什么是线程&#xff1f;:apple:1.2 :apple:线程的优点和缺点:apple:1.3 :apple:页表的大小:apple:1.4 :apple:线程异常和用途:apple:1.5 :apple:进程VS线程:apple: 2 :peach:线程控制:peach:2.1 :apple:POSIX线程库:apple:2.2 :apple…

tp6的runtime/Logs目录下产生大量日记文件,怎么取消自动生成?

一开始查了好多网上提供的&#xff0c;很幸运都是抄袭别人的&#xff0c;没一个成功&#xff0c;最后无奈只能自己解决方法 其实很简单&#xff0c;不用修改config/log.php文件&#xff0c;没用因为只要有登入错误&#xff0c;警告&#xff0c;消息或者sql错误都会写入 解决方…

windows编译poco c++库

背景 最近有了解到poco c库&#xff0c;这里记录下编译及使用过程。 最开始使用的vs studio 2022 和 poco 1.12.4版本编译&#xff0c;不管openssl 使用哪种版本&#xff0c;都会编译报错&#xff0c;最后妥协了。 参考&#xff1a;https://www.bilibili.com/read/cv1416565…

《语文新读写》期刊简介及投稿邮箱

《语文新读写》期刊简介&#xff1a; 《语文新读写》是“国家期刊奖”获奖期刊&#xff0c;中国期刊方阵双效期刊&#xff0c;中国核心期刊&#xff08;遴选&#xff09;数据库收录期刊&#xff0c;被授予上海市期刊优秀编辑部。杂志的主要读者对象为各大院校、中小学各科教师…

安全帽佩戴检测算法模型训练详细流程

一、任务描述 实际施工现场需要对每个进出的人员进行安全帽监测&#xff0c;对未佩戴安全帽的人员平台进行风险告警&#xff0c;通知工作人员并记录下来。 主要包括三类目标物体&#xff1a;头盔&#xff08;helmet&#xff09;&#xff0c;人&#xff08;person&#xff09;…

100种思维模型之耗散结构理论思维模型-96

避免熵死的方法之一就是建立 耗散结构 。 那么&#xff0c;何谓耗散结构理论&#xff1f; 01、何谓耗散结构思维模型‍‍‍ 一、耗散结构理论 1969年&#xff0c;比利时学者 伊里亚普利高津 在对热力学第二定律研究的基础上&#xff0c;提出了 “耗散结构理论”。 他认…

【导航电子地图(MAP)模块功能】

Map功能&#xff1a;提供导航系统中地图描画、地图操作、地图检索的功能。 地图操作功能&#xff1a;地图滚动等。 地图检索功能&#xff1a;附近名称取得、View内检索等。 地图描画功能&#xff1a;是指从地图Data base中读出地点情报&#xff0c;然后按照一定的风格&#…

Meta提出全新参数高效微调方案,仅需一个RNN,Transformer模型GPU使用量减少84%!

近来&#xff0c;随着ChatGPT和GPT-4模型的不断发展&#xff0c;国内外互联网大厂纷纷推出了自家的大语言模型&#xff0c;例如谷歌的PaLM系列&#xff0c;MetaAI的LLaMA系列&#xff0c;还有国内公司和高校推出的一些大模型&#xff0c;例如百度的文心一言&#xff0c;清华的C…

vue3中通过vue-i18n实现国际化

效果图 前言 突然想在vue3项目中使用国际化功能&#xff0c;查阅相关资料后发现和vue2的用法有些出入&#xff0c;记录一下 使用 下载vue-i18n npm i vue-i18n2、准备语言文件 目前我的项目只支持中英文切换&#xff0c;故准备一份中文文件和一份对应的英译文件 创建langur…

七大排序算法——直接插入排序,通俗易懂的思路讲解与图解(完整Java代码)

文章目录 一、排序的概念排序的概念排序的稳定性七大排序算法 二、直接插入排序核心思想代码实现 三、性能分析四、七大排序算法性能对比 一、排序的概念 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#…

【Java进阶之路】NIO基础

一、NIO基础 Java New IO是从Java1.4版本开始引入的一个新的IO api&#xff0c;可以替代以往的标准IO&#xff0c;NIO相比原来的IO有同样的作用和目的&#xff0c;但是使用的方式完全不一样&#xff0c;NIO是面向缓冲区的&#xff0c;基于通道的IO操作&#xff0c;这也让它比传…

美团外卖智能陪伴型导购的探索与实践

相比于其他电商场景&#xff0c;外卖场景对于实时发现和反馈用户兴趣的能力有着更高的要求。近年来&#xff0c;美团外卖算法团队摸索出了一套适用于外卖场景的智能陪伴型导购架构和策略。这一举措已经取得了显著成效&#xff0c;本文将详细介绍外卖搜索技术团队搭建智能陪伴型…

Redis数据结构 — IntSet

目录 整数集合IntSet结构设计 IntSet的升级操作 升级具体过程 升级具体源码 小结 IntSet是Redis中set集合的一种实现方式&#xff0c;基于整数数组来实现&#xff0c;并且具备长度可变、有序等特征。 整数集合IntSet结构设计 整数集合本质上是一块连续内存空间&#xff…

Ubuntu22.04安装飞书

通过以下教程可以快速的安装飞书。 安装包下载 进入飞书下载官网下载飞书Linux客户端 选择deb格式安装包下载 安装方式 方式一&#xff1a;运行安装包安装 双击deb文件&#xff0c;点击install进行安装 方式二&#xff1a;终端命令安装 到安装目录&#xff0c;然后dpkg你的安…