pytest + yaml 框架 -30.jsonpath 表达式提取接口返回结果

前言

pytest-yaml-yoyo 插件可以支持3种表达式提取接口返回结果。本篇详细介绍jsonpath 表达式提取json格式的返回结果。
备注:从v1.2.4 以后新版本不再公开,新功能内部 VIP 学员可以使用,公开版本仅解决bug, 不提供新功能了。

jsonpath 表达式基础语法

关于jsonpath的入门基础可以查看前面这篇https://www.cnblogs.com/yoyoketang/p/13216829.html

相关语法可以参考下表

JSONPath 描述
$ 跟节点
@ 现行节点
. or [] 取子节点
.. 相对节点 就是不管位置,选择所有符合条件的条件
* 匹配所有元素节点
[] 迭代器标示(可以在里面做简单的迭代操作,如数组下标,根据内容选值等)
[,] 支持迭代器中做多选
?() 支持过滤操作
() 支持表达式计算

使用示例, 接口返回如下数据。

{ "store": {
	"book": [ 
	  { "category": "reference",
		"author": "Nigel Rees",
		"title": "Sayings of the Century",
		"price": 8.95
	  },
	  { "category": "fiction",
		"author": "Evelyn Waugh",
		"title": "Sword of Honour",
		"price": 12.99
	  },
	  { "category": "fiction",
		"author": "Herman Melville",
		"title": "Moby Dick",
		"isbn": "0-553-21311-3",
		"price": 8.99
	  },
	  { "category": "fiction",
		"author": "J. R. R. Tolkien",
		"title": "The Lord of the Rings",
		"isbn": "0-395-19395-8",
		"price": 22.99
	  }
	],
	"bicycle": {
	  "color": "red",
	  "price": 19.95
	}
  }
}

jsonpath 取值表达式

JSONPath 表达式 取值结果
$.store.book[*].author 提取book里面全部author: ['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien']
$..author 提取全部author :['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien']
$.store.* store下的全部内容, 包含book和bicycle
$.store..price store 下的全部price: [8.95, 12.99, 8.99, 22.99, 19.95]
$..book[2] 下标获取book里第3个:[{'category': 'fiction', 'author': 'Herman Melville'...}]
$..book[(@.length-1)] 下标获取最后一个:[{'category': 'fiction', 'author': 'J. R. R. Tolkien'...}]
$..book[-1:] 切片获取最后一个:[{'category': 'fiction', 'author': 'J. R. R. Tolkien'...}]
$..book[0,1] 获取第1和第2个:[{'category': 'reference'...}, {'category': 'fiction',...}]
$..book[:2] 切片获取前2个:[{'category': 'reference'...}, {'category': 'fiction',...}]
$..book[?(@.isbn)] 获取book下用isbn 属性的内容:[{'category': 'fiction'... 'isbn': '0-553-21311-3',}, {'category': 'fiction'... 'isbn': '0-395-19395-8'...}]
$..book[?(@.price<10)] 过滤器筛选price小于10:[{'category': 'reference'...'price': 8.95}, {'category': 'fiction'...rice': 8.99}]
$..* 获取全部
$.store.! 获取store下的key: ['book', 'bicycle']
$.store.book[0].title 获取store 下第一个book的title属性:['Sayings of the Century']
$.store.book[(@.length-1)].title 获取store 下最后一个book的title属性:['The Lord of the Rings']
$.store.book[?(@.price < 10)].title 获取store 下price小于10的title属性: ['Sayings of the Century', 'Moby Dick']

(需注意的是python的jsonpath 并不支持函数的使用,如:$..book.length())

?()过滤器运算符

过滤器是用于筛选数组的逻辑表达式。一个典型的过滤器将是 [?(@.age > 18)] ,其中@表示正在处理的当前项目。
可以使用逻辑运算符&& 和 ||创建更复杂的过滤器。 字符串文字必须用单引号或双引号括起来 ([?(@.name == 'yoyo')] 或者 [?(@.name== "yoyo")]).

操作符 描述
== left等于right(注意1不等于'1')
!= 不等于
< 小于
<= 小于等于
> 大于
>= 大于等于
=~ 匹配正则表达式[?(@.name =~ /foo.*?/i)]
in 左边存在于右边 [?(@.size in ['S', 'M'])]
nin 左边不存在于右边
size (数组或字符串)长度
empty (数组或字符串)为空

?()过滤表达式的使用

?()过滤表达式。 表达式必须求值为一个布尔值,表达式一般结合@获取当前节点来过滤

import jsonpath
# 上海悠悠 wx:283340479
# blog:https://www.cnblogs.com/yoyoketang/

s = {
	"code": 0,
	"msg": "success!",
	"data": [{
		"id": 154,
		"create_time": "2021-01-20 22:38:16",
		"update_time": "2021-01-20 22:38:16",
		"goodsname": "《selenium入门到精通到放弃》",
		"goodscode": "sp_210001",
		"merchantid": "",
		"merchantname": "",
		"goodsprice": 20.0,
		"stock": 0,
		"goodsgroupid": 0,
		"goodsstatus": 1
	}, {
		"id": 1,
		"create_time": "2021-01-17 15:14:25",
		"update_time": "2021-01-20 22:21:51",
		"goodsname": "《jmeter 入门到精通》",
		"goodscode": "sp_100049",
		"merchantid": "10001",
		"merchantname": "悠悠学堂",
		"goodsprice": 100.0,
		"stock": 1,
		"goodsgroupid": 1,
		"goodsstatus": 1
	}, {
		"id": 150,
		"create_time": "2021-01-19 23:43:47",
		"update_time": "2021-01-19 23:43:47",
		"goodsname": "《cypress 入门到精通》",
		"goodscode": "sp_10002232",
		"merchantid": "1000122",
		"merchantname": "悠悠学堂",
		"goodsprice": 49.9,
		"stock": 100,
		"goodsgroupid": 0,
		"goodsstatus": 1
	}, {
		"id": 148,
		"create_time": "2021-01-19 23:42:20",
		"update_time": "2021-01-19 23:42:20",
		"goodsname": "《appium 入门到精通》",
		"goodscode": "sp_426001",
		"merchantid": "42601",
		"merchantname": "悠悠学堂",
		"goodsprice": 99.9,
		"stock": 100,
		"goodsgroupid": 0,
		"goodsstatus": 1
	}, {
		"id": 147,
		"create_time": "2021-01-19 22:22:41",
		"update_time": "2021-01-19 22:22:41",
		"goodsname": "《pytest 入门到精通》",
		"goodscode": "sp_100119",
		"merchantid": "",
		"merchantname": "",
		"goodsprice": 10.0,
		"stock": 0,
		"goodsgroupid": 0,
		"goodsstatus": 1
	}]
}

1.找出商品价格大于20的全部商品信息

# 价格大于20的
data1 = jsonpath.jsonpath(s, '$.data[?(@.goodsprice > 20)]')
print(data1)

# 价格大于20的goodscode
goodscodes = jsonpath.jsonpath(s, '$.data[?(@.goodsprice > 20)].goodscode')
print(goodscodes)   # ['sp_100049', 'sp_10002232', 'sp_426001']

# 价格大于20的goodsname
goodsnames = jsonpath.jsonpath(s, '$.data[?(@.goodsprice > 20)].goodsname')
print(goodsnames)  # ['《jmeter 入门到精通》', '《cypress 入门到精通》', '《appium 入门到精通》']

2.取出 'goodscode': 'sp_100049' 对应的 goodsname

# 取出 'goodscode': 'sp_100049' 对应的 goodsname
name2 = jsonpath.jsonpath(s, '$.data[?(@.goodscode == "sp_100049" )].goodsname')
print(name2)  # ['《jmeter 入门到精通》']

3.取出 'goodscode': 'sp_100049' 和 'goodscode': 'sp_100119' 对应的 goodsname

# in 包含在内 nin不存在
name3 = jsonpath.jsonpath(s, '$.data[?(@.goodscode in ["sp_100049", "sp_100119"])].goodsname')
print(name3)  # ['《jmeter 入门到精通》', '《pytest 入门到精通》']

在 yaml 用例中使用 jsonpath 表达式提取示例

/api/test/demo 接口返回内容如下

# 上海悠悠 wx:283340479
# blog:https://www.cnblogs.com/yoyoketang/

{
    "code": 0,
    "msg": "成功success!",
    "data": [
        {
            "age": 20,
            "create_time": "2019-09-15",
            "id": 1,
            "mail": "283340479@qq.com",
            "name": "yoyo",
            "sex": "M"
        },
        {
            "age": 21,
            "create_time": "2019-09-16",
            "id": 2,
            "mail": "123445@qq.com",
            "name": "yoyo111",
            "sex": "M"
        }
    ]
}

test_jsonpath.yml 测试用例文件内容

# 上海悠悠 wx:283340479
# blog:https://www.cnblogs.com/yoyoketang/

test_demo:
  name: jsonpath取值示范
  request:
    url: http://127.0.0.1:8000/api/test/demo
    method: GET
  validate:
    - eq: ['$.code', 0]
    - eq: ['$.msg', 成功success!]
    - eq: ['$..name', ["yoyo", "yoyo111"]]
    - eq: ['$.data[0].name', yoyo]
    - eq: ['$.data[(@.length-1)].name', yoyo111]
    - eq: ['$.data[?(@.age > 20)].name', yoyo111]
    - eq: ['$.data[?(@.name == "yoyo")].mail', 283340479@qq.com]
    - eq: ['$.data[?(@.name in ["yoyo", "admin"])].mail', 283340479@qq.com]
    - len_eq: ['$.data[?(@.age > 10)]', 2]
    - len_eq: ['$..name]', 2]

运行日志:

2023-05-26 09:31:33 [INFO]: validate 校验结果-> eq: [0, 0]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> eq: [成功success!, 成功success!]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> eq: [['yoyo', 'yoyo111'], ['yoyo', 'yoyo111']]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> eq: [yoyo, yoyo]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> eq: [yoyo111, yoyo111]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> eq: [yoyo111, yoyo111]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> eq: [283340479@qq.com, 283340479@qq.com]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> eq: [283340479@qq.com, 283340479@qq.com]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> len_eq: [[{'age': 20, 'create_time': '2019-09-15', 'id': 1, 'mail': '2
83340479@qq.com', 'name': 'yoyo', 'sex': 'M'}, {'age': 21, 'create_time': '2019-09-16', 'id': 2, 'mail': '123445@qq.co
m', 'name': 'yoyo111', 'sex': 'M'}], 2]
2023-05-26 09:31:33 [INFO]: validate 校验结果-> len_eq: [['yoyo', 'yoyo111'], 2]

网易云完整视频课程https://study.163.com/course/courseMain.htm?courseId=1213419817&share=2&shareId=480000002230338
报名咨询wx:283340479 (已报名的同学学习过程中有问题,都可以协助解决)

posted @ 2023-05-26 09:09  上海-悠悠  阅读(355)  评论(0编辑  收藏  举报