接口测试 04 -- Jsonpath断言、接口关联处理

1. JsonPath基本介绍

1.1 JsonPath简介

JsonPath是一种用于在JSON数据中定位和提取特定数据的表达式语言。它类似于XPath用于XML的定位和提取,可以帮助我们灵活地从复杂的JSON结构中获取所需的数据。

 1.2 JsonPath的特点

● JsonPath可处理的报文类型为字典类型

● 通过JsonPath成功获得的内容,会以list的形式进行返回,也就意味着你的 JsonPath是可以有一个值或者多个值同时存在的。

● 如果要基于JsonPath来处理json数据,就一定要去同步处理list

● JsonPath定义中,如果表达式出现错误,则会返回False(布尔类型的值)

● JsonPath要么返回False,要么返回list

1.3 JsonPath安装

pip install jsonpath    # 安装命令
pip show jsonpath       # 安装效验

1.4 JsonPath实际运行场景

对应做软件测试来说:

1. 主要能够通过这个方式提取数据
2. 业务场景: 断言 、接口关联

常规的报文也避免不了比较复杂的情况,如下所示包含了一个人员的信息,包括姓名、年龄、邮箱、地址、爱好、教育背景和参与的项目。
它展示了JSON数据的嵌套结构和多种数据类型的使用,那么我们应该如何进行解决呢?
{
"name": "Alice",
"age": 25,
"email": "alice@example.com",
"address": {
"street": "456 Elm Street",
"city": "Los Angeles",
"country": "USA"
},
"hobbies": ["reading", "traveling", "cooking"],
"education": [
{
"degree": "Bachelor's",
"major": "Computer Science",
"university": "ABC University",
"year": 2018
},
{
"degree": "Master's",
"major": "Business Administration",
"university": "XYZ University",
"year": 2020
}
],
"projects": [
{
"name": "Project A",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"contributors": ["John", "Sarah", "Mike"],
"completed": "true"
},
{
"name": "Project B",
"description": "Nulla vel sagittis elit. Vivamus auctor massa in lacinia pellentesque.",
"contributors": ["Alice", "David"],
"completed": "false"
}
],
"is_active": "true"
}

举一个栗子:提取上面这段代码中education里的年份值

更多提取信息,语法格式,先下面“JsonPath基本格式规范-示例参考

从上图可以看出:返回的数据类型是列表

1.5 JsonPath基本格式规范

以下是一些JsonPath的常用语法和示例:

附:jsonpath在线解析器 http://www.atoolbox.net/Tool.php?Id=792

$ 根节点,也是所有JsonPath表达式的开始
. 表示获取子节点
.. 表示获取所有符合条件的内容
* 代表所有的元素节点
[index] 表示迭代器的标示(可以用于处理下标等情况)
[,] 表示多个结果的选择
[start:end] 指定范围内的元素
?(@.property == value) 表示过滤操作 # 比较运算符
@ 表示当前节点
示例参考:
① 基本语法
$ :根节点,也是所有JsonPath表达式的开始
. :当前节点
.. :递归下级节点
② 属性操作
$.property :选择指定属性
$['property'] :选择指定属性,属性名带有特殊字符时使用

③ 数组操作(含头不含尾)

$.array[index] :选择指定索引处的元素
$.array[start:end] :选择指定范围内的元素

 ④ 过滤器(比较运算符都可以用)

$.array[?(@.property == value)] :根据条件过滤数组元素
$.array[?(@.property > value)] :根据条件过滤数组元素

⑤ 路径组合

$.parent.child :选择父节点下的子节点
$.parent[*].child :选择父节点下所有子节点的某个属性

1.6 JsonPath断言实例

一个登陆接口的正向用例:

断言 :提取响应数据和期望数据进行对比

import jsonpath
import requests
import json# 完整的请求url
url = "http://xxxx域名/index.php?s=/api/user/login" # 公共参数
pulic_data = {"application": "app", "application_client_type": "weixin"}
# 登陆接口请求参数
data = {"accounts": "hailey", "pwd": "hailey123", "type": "username"}json_data = json.dumps(data)  # 将请求参数转为json格式# 指定请求头的参数的数据格式为json
header = {'Content-Type':'application/json;charset=utf-8'}# 发送请求    
res = requests.post(url,params=pulic_data,headers=header,data=json_data)print(res.json())exData = "登录成功"   # 期望结果# 实际结果:最后记得加索引,不然会报错
SjData = jsonpath.jsonpath(res.json(),"$.msg")[0]  
# 断言 期望结果结果等于实际结果,并格式化输出期望结果、实际结果
assert exData == SjData,"期望结果是:{0},实际结果是:{1}".format(exData,SjData)

所有工具中的断言都一样,如果断言成功,则不会显示断言信息,也不会报错

如果断言失败,则报错信息中显示断言信息

2. 接口关联

2.1 接口关联意义

接口关联是在进行接口测试时,将一个接口的返回结果中的某些数据提取出来,然后作为后续接口请求的参数或者验证的依据。通过接口关联,可以实现接口间的数据传递和依赖关系的建立。

2.2 接口关联类型

接口关联通常分为两种类型:请求关联和响应关联。
1. 请求关联
提取关键参数 :在一个接口的请求中,某些参数的值是由之前接口的响应结果提供的。需要提取出这些关键参数,并将其作为后续接口的请求参数。
例如,一个接口的请求中需要使用到某个用户的登录令牌(token),可以通过在登录接口的响应结果中提取出令牌(token),然后在后续接口的请求中使用。
----------->>>
2. 响应关联
验证关键数据 :在一个接口的响应结果中,某些数据是需要验证的,可以将这些数据提取出来,并进行断言或者其他验证操作。
例如,一个接口的响应结果中包含了某个订单的状态信息,可以将该状态信息提取出来,然后进行断言,验证订单是否处于正确的状态。

2.3 加入购物车案例

这里还是基于上个案例的登录接口(某电商平台):

1. 首先登录成功,提取token值。

2. 通过提取的token,将商品加入购物车。

使用josnpath提取token

第一步:将打印信息换成text文件,方便接下来去调试

import json
import requests
import jsonpathurl = "http://xxxx域名/index.php?s=/api/user/login" 
pulic_data = {"application": "app", "application_client_type": "weixin"}
data = {"accounts": "hailey", "pwd": "hailey123", "type": "username"}header = {'Content-Type': 'application/json; charset=utf-8'}
json_data = json.dumps(data)# --------------------发送接口请求---------------------------
res = requests.post(url, params=pulic_data, headers=header,data=json_data) # 正确的演示# --------------------获取响应数据---------------------------
print(res.text)    # 改成获取text文本内容# --------------------获取数据进行断言处理---------------------------
exData = "登录成功"
SjData = jsonpath.jsonpath(res.json(),"$.msg")[0]
assert exData == SjData, "期望结构是:{0},实际结果是:{1}".format(exData, SjData)

第二步:将上一步的代码运行,复制控制台输出的响应内容,全部黏贴到json在线工具中,美化一下格式:JSON在线解析及格式化验证 - JSON.cn

第三步:复制黏贴美化后的响应内容,到josnpath在线工具中,进行调试

ps:如果代码能力强的,可以跳过这两步,直接写josnpath提取token的代码

josnpath提取响应信息中的token,有上面两种写法,第二种更简单

第四步:去完善代码

import json
import requests
import jsonpathurl = "http://xxxx域名/index.php?s=/api/user/login" 
pulic_data = {"application": "app", "application_client_type": "weixin"}
data = {"accounts": "hailey", "pwd": "hailey123", "type": "username"}header = {'Content-Type': 'application/json; charset=utf-8'}
json_data = json.dumps(data)# --------------------发送接口请求---------------------------
res = requests.post(url, params=pulic_data, headers=header,data=json_data) # 正确的演示# --------------------获取响应数据---------------------------
print("响应信息:",res.text)    # 改成获取text文本内容# --------------------获取数据进行断言处理---------------------------
exData = "登录成功"
SjData = jsonpath.jsonpath(res.json(),"$.msg")[0]
assert exData == SjData, "期望结构是:{0},实际结果是:{1}".format(exData, SjData)# --------------------获提取token值---------------------------
token =jsonpath.jsonpath(res.json(),"$..token")[0]
print("提取出来的token值:",token)

加入购物车

完整代码:

import json
import requests
import jsonpathurl = "http://xxxx域名/index.php?s=/api/user/login" 
pulic_data = {"application": "app", "application_client_type": "weixin"}
data = {"accounts": "hailey", "pwd": "hailey123", "type": "username"}header = {'Content-Type': 'application/json; charset=utf-8'}
json_data = json.dumps(data)# --------------------发送接口请求---------------------------
res = requests.post(url, params=pulic_data, headers=header,data=json_data) # 正确的演示# --------------------获取响应数据---------------------------
print("响应信息:",res.text)    # 改成获取text文本内容# --------------------获取数据进行断言处理---------------------------
exData = "登录成功"
SjData = jsonpath.jsonpath(res.json(),"$.msg")[0]
assert exData == SjData, "期望结构是:{0},实际结果是:{1}".format(exData, SjData)# --------------------获提取token值---------------------------
token =jsonpath.jsonpath(res.json(),"$..token")[0]
print("提取出来的token值:",token)# --------------------加入购物车---------------------------
# 加入购物车请求参数
data = {"goods_id":"10", # 商品id"spec": "",      # 商品规格,无规格"stock": 1       # 加入数量
}# 公共参数
params = {"application": "app","application_client_type": "weixin","token": token
}
res = requests.post(url="http://xxxx域名/index.php?s=api/cart/save", params=params, json=data)
print(res.json())

打开web页面:也显示加入成功

拿到对应的项目,一定要梳理出来对应的业务流程及它对应接口之间的关联关系
任何项目:都需要理解需求、业务流程

=====================================================================

基于这个思路:还可以梳理出不同的测试场景
1. 浏览商品--加入购物车 (有规格/无规格) --从购物车去提交订单
a.选择商品[一般对应列表都是会有 (购物车)列表接口,都会有id)
b.选择对应的地址
c.选择支付方式)--订单支付

---------------->>>
2. 浏览商品--加入购物车--从购物车去提交订单--取消订单

---------------->>>
3. 浏览商品--提交订单
a.从数据库找商品表 (找到商品名称字段)
b.从页面上获取 (id,一般会在页面对应的url中)

=====================================================================

可以看出,接口测试,与功能测试的思路、场景都是一样的

再换一个有商品规格的商品,加入购物车

import json
import requests
import jsonpathurl = "http://xxxx域名/index.php?s=/api/user/login" 
pulic_data = {"application": "app", "application_client_type": "weixin"}
data = {"accounts": "hailey", "pwd": "hailey123", "type": "username"}header = {'Content-Type': 'application/json; charset=utf-8'}
json_data = json.dumps(data)# --------------------发送接口请求---------------------------
res = requests.post(url, params=pulic_data, headers=header,data=json_data) # 正确的演示# --------------------获取响应数据---------------------------
print("响应信息:",res.text)    # 改成获取text文本内容# --------------------获取数据进行断言处理---------------------------
exData = "登录成功"
SjData = jsonpath.jsonpath(res.json(),"$.msg")[0]
assert exData == SjData, "期望结构是:{0},实际结果是:{1}".format(exData, SjData)# --------------------获提取token值---------------------------
token =jsonpath.jsonpath(res.json(),"$..token")[0]
print("提取出来的token值:",token)# --------------------加入购物车---------------------------
# 加入购物车请求参数,有规格值
data = {"goods_id": "11","spec": [{"type": "尺寸","value": "L"}],"stock": "10"}# 公共参数
params = {"application": "app","application_client_type": "weixin","token": token
}
res = requests.post(url="http://xxxx域名/index.php?s=api/cart/save", params=params, json=data)
print(res.json())

再加一个查看购物车接口、并提取购物车列表Id:

import json
import requests
import jsonpathurl = "http://xxxx域名/index.php?s=/api/user/login" 
pulic_data = {"application": "app", "application_client_type": "weixin"}
data = {"accounts": "hailey", "pwd": "hailey123", "type": "username"}header = {'Content-Type': 'application/json; charset=utf-8'}
json_data = json.dumps(data)# --------------------发送接口请求---------------------------
res = requests.post(url, params=pulic_data, headers=header,data=json_data) # 正确的演示# --------------------获取响应数据---------------------------
print("响应信息:",res.text)    # 改成获取text文本内容# --------------------获取数据进行断言处理---------------------------
exData = "登录成功"
SjData = jsonpath.jsonpath(res.json(),"$.msg")[0]
assert exData == SjData, "期望结构是:{0},实际结果是:{1}".format(exData, SjData)# --------------------获提取token值---------------------------
token =jsonpath.jsonpath(res.json(),"$..token")[0]
print("提取出来的token值:",token)# --------------------加入购物车---------------------------
# 加入购物车请求参数,有规格值
data = {"goods_id": "11","spec": [{"type": "尺寸","value": "L"}],"stock": "10"}# 公共参数
params = {"application": "app","application_client_type": "weixin","token": token
}
res = requests.post(url="http://xxxx域名/index.php?s=api/cart/save", params=params, json=data)
print(res.json())# --------------------购物车列表---------------------------
# 公共参数,查看购物车没有请求参数
params = {"application": "app","application_client_type": "weixin","token": token
}
res = requests.get(url="http://xxx域名/index.php?s=api/cart/index", params=params)
print(res.json())
cardid  =jsonpath.jsonpath(res.json(),"$..id")[0] # 推荐的用法
print("提取出来的商品id:>>",cardid)

总结

思路

web自动化、api接口自动化,本质上都是模拟用户操作,所以手工测试有哪些步骤、自动化同样也有哪些步骤。

列表页面:商品列表、购物列表,任何列表都有增删改查,所以都会有对应的接口,接口关联依赖上一个接口的数据,一般都会有一个 (列表)唯一值 id。

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

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

相关文章

4.servera修改主机名,配置网络,以及在cmd中远程登录servera的操作

1.先关闭这两节省资源 2.对于新主机修改主机名,配置网络 一、配置网络 1.推荐图形化界面nmtui 修改完成后测试 在redhat ping一下 在redhat远程登录severa 2、使用nmcli来修改网络配置 2.1、配置要求:主机名: node1.domain250.exam…

C++:类与对象(上)

C:类与对象(上) 类的引入类的定义访问限定符类域实例化对象模型this指针 类的引入 C的类是基于C语言的结构体优化出来的,那我们先来看一看C对结构体有哪些优化点。 C语言与C的结构体的类型名称略有区别,我们看一个案…

寒假每日一题-小苹果

小 Y 的桌子上放着 n 个苹果从左到右排成一列,编号为从 1 到 n。 小苞是小 Y的好朋友,每天她都会从中拿走一些苹果。 每天在拿的时候,小苞都是从左侧第 1个苹果开始、每隔 2 个苹果拿走 1个苹果。 随后小苞会将剩下的苹果按原先的顺序重新…

【Leetcode】接雨水(双指针、单调栈)

目录 &#x1f4a1;题目描述 &#x1f4a1;双指针解法 &#x1f4a1;单调栈解法 &#x1f4a1;题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 提示&#xff1a; n height.length1 < n…

010-新手如何建立一个属于自己的图像处理FPGA/ZYNQ框架(自己的用着才舒服,内容非常全面!)

文章目录 前言一、图像处理框架二、图像采集输入1.常用视频流格式&#xff1a;Rgb565/Bayer1.RGB565数据流格式2.Bayer阵列数据流格式 2.图像预处理&#xff1a;时钟域同步/去马赛克/色彩空间转换/滤波1.时钟域同步2.图像去马赛克化3.色彩空间转换4.滤波 三、图像算法处理1.图像…

【后端】深入浅出Node.js

文章目录 1.Node简介1.1 诞生历程1.2 阻塞IO和异步IO 【后端目录贴】 1.Node简介 1.1 诞生历程 Node特点 事件驱动、非阻塞I/O node和chrome浏览器区别 除了HTML、WebKit和显卡这些UI相关技术没有支持外&#xff0c;Node结构与Chrome十分相似&#xff0c;他们都是基于事件驱动…

Vue 组件通信方式

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

AI大模型开发架构设计(1)——LLM大模型Agent剖析和应用案例实战

文章目录 LLM大模型Agent剖析和应用案例实战1 从 LLM 大模型到智能体演进技术语言模型是什么&#xff1f;大语音模型是什么&#xff1f;大语言模型日新月异LLM大模型存在局限性LLM Agent来势凶凶LLM Agent增长迅猛LLM Agent是什么&#xff1f; 2 LLM Agent 架构深度剖析规划能力…

OpenCV实战——OpenCV.js介绍

OpenCV实战——OpenCV.js介绍 0. 前言1. OpenCV.js 简介2. 网页编写3. 调用 OpenCV.js 库4. 完整代码相关链接 0. 前言 本节介绍如何使用 JavaScript 通过 OpenCV 开发计算机视觉算法。在 OpenCV.js 之前&#xff0c;如果想要在 Web 上执行一些计算机视觉任务&#xff0c;必须…

线性代数:矩阵运算(加减、数乘、乘法、幂、除、转置)

目录 加减 数乘 矩阵与矩阵相乘 矩阵的幂 矩阵转置 方阵的行列式 方阵的行列式&#xff0c;证明&#xff1a;|AB| |A| |B| 加减 数乘 矩阵与矩阵相乘 矩阵的幂 矩阵转置 方阵的行列式 方阵的行列式&#xff0c;证明&#xff1a;|AB| |A| |B|

核密度曲线(python

目录 1.代码&#xff1a;2.效果&#xff1a;小结&#xff1a; 1.代码&#xff1a; import pandas as pd import matplotlib.pyplot as plt # 读入数据 file r123.xlsx sheet Sheet2 col S213 # 标题名称 title col 供订比曲线 xlabel 供订比 # 横轴显示范围 xleft 0 xr…

解决 conda新建虚拟环境只有一个conda-meta文件&conda新建虚拟环境不干净

像以前一样通过conda 新建虚拟环境时发现环境一团糟&#xff0c;首先新建虚拟环境 conda create -n newenv这时候activate newenv&#xff0c;通过pip list&#xff0c;会发现有很多很多的包&#xff0c;都是我在其他环境用到的。但诡异的是&#xff0c;来到anaconda下env的目…

加固密码安全:保护您的个人信息

一、引言 在数字化时代&#xff0c;密码安全是保护个人信息和数据的重要环节。然而&#xff0c;许多人在创建和管理密码时存在一些常见的安全漏洞&#xff0c;如使用弱密码、重复使用密码等。本文将详细介绍密码安全的重要性&#xff0c;并提供一些有效的方法和技巧&#xff0…

【嘉立创EDA-PCB设计指南】4.模块化布局

前言&#xff1a;本文对本专栏中的【嘉立创EDA-PCB设计指南】前面绘制的原理图进行模块化布局&#xff0c;首先进行预布局&#xff08;将每个模块放一起&#xff09;&#xff0c;然后进行精细化布局&#xff08;按照原理图来精细化布局&#xff09;。 目录 模块化预布局 模块…

软件工程应用题汇总

绘制数据流图(L0/L1/L2) DFD/L0&#xff08;基本系统模型&#xff09; 只包含源点终点和一个处理(XXX系统) DFD/L1&#xff08;功能级数据流图&#xff09;在L0基础上进一步划分处理(XXX系统) 个人理解 DFD/L2&#xff08;在L1基础上进一步分解后的数据流图&#xff09; 数据…

NumPy2要来了,但先别急!

B站&#xff1a;啥都会一点的研究生公众号&#xff1a;啥都会一点的研究生 如果你正在使用 Python 编写代码&#xff0c;那么很有可能正在直接或间接地使用 NumPy 如Pandas、Scikit-Image、SciPy、Scikit-Learn、AstroPy…这些都依赖于 NumPy NumPy 2 是一个新的重要版本&am…

XXE漏洞概念

1、XXE漏洞概念 XXE(XML External Entity Injection) 又称为XML外部实体注入。 XML是一种类似于HTML&#xff08;超文本标记语言&#xff09;的可扩展标记语言&#xff0c;是用于标记电子文件使其具有结构性的标记语言&#xff0c;可以用来标记数据、定义数据类型&#xff0c…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例4-7 datalist

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>datalist</title> </head><body> <input id"address" list"addressList"> <datalist id"addressList"…

Web3艺术市场:NFT与数字创作的结合

在数字时代&#xff0c;随着区块链技术的崛起&#xff0c;一种新型数字资产&#xff0c;非同质化代币&#xff08;NFT&#xff09;&#xff0c;正逐渐改变传统艺术市场的格局。这种数字化的艺术品售卖方式成为了Web3艺术市场的代表&#xff0c;推动着数字创作与艺术市场的结合。…

【C++干货铺】C++11新特性——右值引用、移动构造、完美转发

个人主页点击直达&#xff1a;小白不是程序媛 C系列专栏&#xff1a;C干货铺 代码仓库&#xff1a;Gitee 目录 左值与左值引用 右值与右值引用 左值引用和右值引用的比较 左值引用总结&#xff1a; 右值引用总结&#xff1a; 左值引用的作用和意义 右值引用的使用场景和…