Python 使用 JsonPath 完成接口自动化测试中参数关联和数据验证

背景:

  1. 接口自动化测试实现简单、成本较低、收益较高,越来越受到企业重视
  2. RESTFul 风格的 API 设计大行其道
  3. JSON 成为主流的轻量级数据交换格式

痛点

接口关联

数据验证

   {"status":1,"msg":"登录成功"}
{"status":1,"code":"10001","data":[{"id":1,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"1","unfinishedInterest":"1.0","unfinishedPrincipal":"0","repaymentDate":"2018-05-27 12:24:01","actualRepaymentDate":null,"status":"0"},{"id":2,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"2","unfinishedInterest":"1.0","unfinishedPrincipal":"0","repaymentDate":"2018-06-27 12:24:01","actualRepaymentDate":null,"status":"0"},{"id":3,"investId":"1","createTime":"2018-04-27 12:24:01","terms":"3","unfinishedInterest":"1.0","unfinishedPrincipal":"100.00","repaymentDate":"2018-07-27 12:24:01","actualRepaymentDate":null,"status":"0"}],"msg":"获取信息成功"}

上面的 JSON 结构嵌套了很多信息,完整的匹配几乎不可能成功。比如其中的 createTime 信息,根据执行接口测试用例的时间每次都不一样。同时这个时间是响应结果中较为次要的信息,在进行接口自动化测试时,是可以选择被忽略的。

解决方案

JsonPath 可以完美解决上面的痛点。通过 JsonPath 可以从多层嵌套的 JSON 中解析出所需要的值。

JsonPath

$.store.book[0].title 
$['store']['book'][0]['title']

运算符(Operators)

运算符 说明
$ 根元素
@ 当前元素
* 通配符,可以表示任何元素
.. 递归搜索
. 子节点(元素)
['' (, '')] 一个或者多个子节点
[ (, )] 一个或者多个数组下标
[start:end] 数组片段,区间为[start,end)
[?()] 过滤器表达式,其中表达式结果必须是 boolean 类型,如可以是比较表达式或者逻辑表达式

JsonPath 案例

JSON

{
    "lemon": {
        "teachers": [
            {
                "id": "101",
                "name": "华华",
                "addr": "湖南长沙",
                "age": 25
            },
             {
                "id": "102",
                "name": "韬哥",
                "age": 28
            },
            {
                "id": "103",
                "name": "Happy",
                "addr": "广东深圳",
                "age": 16
            },
             {
                "id": "104",
                "name": "歪歪",
                "addr": "广东广州",
                "age": 29
            }
        ],
        "salesmans": [
            {
                "id": "105",
                "name": "毛毛",
                "age": 17
            },
             {
                "id": "106",
                "name": "大树",
                "age": 27
            }
        ]
    },
 "avg": 25
}

JsonPath 例子及说明

JsonPath 路径说明
$.lemon.teachers[*].name 获取所有老师的的名称
$..name 获取所有人的名称
$.lemon.* 所有的老师和销售
$.lemon..age 所有人的年龄
$..age 所有人的年龄
$.lemon.teachers[*].age 所有老师的年龄
$.lemon.teachers[3] 索引为 3(第 4 个)老师的信息
$..teachers[3] 索引为 3(第 4 个)老师的信息
$.lemon.teachers[-2] 倒数第 2 个老师的信息
$..teachers[-2] 倒数第 2 个老师的信息
$..teachers[1,2] 第 2 到第 3 个老师的信息
$..teachers[:2] 索引 0(包含)到索引 2(不包含)的老师信息
$..teachers[1:3] 索引 1(包含)到索引 3(不包含)的老师信息
$..teachers[-2:] 最后的两个老师的信息
$..teachers[2:] 索引 2 开始的所有老师信息
$..teachers[?(@.addr)] 所有包含地址的老师信息(jsonpath_rw 不支持)
$.lemon.teachers[?(@.age < 20)] 所有年龄小于 20 的年龄信息(jsonpath_rw 不支持)

使用 jsonpath 模块

安装 jsonpath 模块

  pip install jsonpath==0.75

解析

# 1:导入相关模块
import json
import jsonpath

# 2: 准备json字符串
jsonStr = '''
          {
    "lemon": {
        "teachers": [
            {
                "id": "101",
                "name": "华华",
                "addr": "湖南长沙",
                "age": 25
            },
             {
                "id": "102",
                "name": "韬哥",
                "age": 28
            },
            {
                "id": "103",
                "name": "Happy",
                "addr": "广东深圳",
                "age": 16
            },
             {
                "id": "104",
                "name": "歪歪",
                "addr": "广东广州",
                "age": 29
            }
        ],
        "salesmans": [
            {
                "id": "105",
                "name": "毛毛",
                "age": 17
            },
             {
                "id": "106",
                "name": "大树",
                "age": 27
            }
        ]
    },
 "avg": 25
}
'''

# 3:加载json字符串为json对象
json_obj = json.loads(jsonStr)

# 4:使用jsonpath模块的jsonpath方法提取信息
# eg1: 提取所有包含addr属性的老师信息,结果为list类型
results = jsonpath.jsonpath(json_obj,"$..teachers[?(@.addr)]")  
print(results)
# 输出结果:[{'id': '101', 'name': '华华', 'addr': '湖南长沙', 'age': 25}, {'id': '103', 'name': 'Happy', 'addr': '广东深圳', 'age': 16}, {'id': '104', 'name': '歪歪', 'addr': '广东广州', 'age': 29}]

# eg2:提取所有年龄小于20岁的老师的name,结果为list类型
results2 = jsonpath.jsonpath(json_obj,"$.lemon.teachers[?(@.age < 20)].name")  
print(results2)
# 输出结果为:['Happy']

使用 jsonpath_rw

安装 jsonpath_rw 模块

 pip install jsonpath-rw

解析

# 1:导入相关模块
import json
from jsonpath_rw import jsonpath, parse

# 2: 准备json字符串
jsonStr = '''
  # 同上(略)
'''

# 3:加载为json对象
json_obj = json.loads(jsonStr)

# 4:采用parse创建jsonpath对象(该案例是得到所有的老师name)
jsonpath_expr = parse('$.lemon.teachers[*].name')

# 5:通过jsonPath检索json后返回匹配的数据,类型是DatumInContext的list
datumInContexts = jsonpath_expr.find(json_obj)
# 采用列表推导式检索出所有匹配的值
values = [datum.value for datum in datumInContexts]
print(values)
# 输出结果为:['华华', '韬哥', 'Happy', '歪歪']

# 案例2:提取索引为4的老师的name
jsonpath_expr = parse('$.lemon.teachers[3].name')
datumInContexts = jsonpath_expr.find(json_obj)
print(datumInContexts)
values = [datum.value for datum in datumInContexts]
print(values)
# 结果为:['歪歪']

更多 jsonpath_rw 用法参考:

https://pypi.org/project/jsonpath-rw/

相关帖子

Java 使用 JsonPath 完成接口自动化测试中参数关联和数据验证

通过 JSON Schema 完成接口自动化测试的数据验证

2 操作
happy 在 2020-09-14 17:33:03 更新了该帖
happy 在 2020-08-06 16:49:34 更新了该帖
10 回帖
请输入回帖内容 ...
请输入回帖内容 ...