提高接口自动化测试效率:使用 JMESPath 实现断言和数据提取!

前言

做接口自动化,断言是比不可少的。如何快速巧妙的提取断言数据就成了关键,当然也可以提高用例的编写效率。笔者在工作中接触到了JMESPath,那到底该如何使用呢?带着疑惑一起往下看。

JMESPath是啥?

JMESPath 是一种用于查询和转换 JSON 数据的简洁、强大的查询语言。它提供了一种灵活的方式来从复杂的 JSON 结构中提取所需的数据,并支持各种操作和函数,以满足不同的查询需求。

JMESPath如何使用?

在使用 JMESPath 查询 JSON 数据之前,我们需要安装 jmespath 库。安装命令如下:

pip install jmespath

简单路径表达式

假设我们有以下的 JSON 数据:

data = {
    "name": "Alice",
    "age": 25,
    "email": "[email protected]"
}

我们想要从中提取"name"属性的值。使用 JMESPath,我们可以编写以下代码:

import jmespath
​
expression = "name"
result = jmespath.search(expression, data)
​
print(result)  # 输出:Alice

这里,我们定义了一个路径表达式"name",然后使用jmespath.search()函数将该表达式应用于数据data上。结果会被存储在result变量中,并输出为"Alice"

现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:110685036

嵌套属性访问

当 JSON 数据具有嵌套结构时,可以使用点号 . 连接多个属性名来表示深层的属性访问。考虑以下 JSON 数据:

data = {
    "person": {
        "name": "Alice",
        "age": 25,
        "email": "[email protected]"
    }
}

我们要提取"name"属性,可以使用以下路径表达式:

expression = "person.name"
result = jmespath.search(expression, data)
​
print(result)  # 输出:Alice

这里,我们将属性名 "person" 和 "name" 使用点号 . 连接起来,表示深层的属性访问。

复杂嵌套查询

假设我们有一个包含学生信息和他们的课程成绩的更复杂的 JSON 数据,如下所示:

data = {
    "students": [
        {
            "name": "Alice",
            "courses": [
                {"name": "Math", "score": 95},
                {"name": "English", "score": 88}
            ]
        },
        {
            "name": "Bob",
            "courses": [
                {"name": "Math", "score": 75},
                {"name": "English", "score": 92}
            ]
        }
    ]
}

现在,假设我们想要获取每个学生的数学成绩。可以通过以下表达式实现:

expression = "students[].courses[?name == 'Math'].score"

再次执行查询并打印结果:

result = jmespath.search(expression, data)
print(result)

输出结果将是一个包含每个学生数学成绩的列表:

[[95], [75]]

列表索引

对于 JSON 中的列表属性,可以使用方括号 [index] 来指定索引位置来检索数据。假设我们有以下 JSON 数据:

data = {
    "fruits": ["apple", "banana", "cherry"]
}

我们想要提取第二个元素,即"banana"。可以使用以下路径表达式:

expression = "fruits[1]"
result = jmespath.search(expression, data)
​
print(result)  # 输出:banana

这里,我们使用方括号 [1] 来指定索引位置,表示提取第二个元素。

过滤器

JMESPath 提供了过滤器功能,使我们能够根据特定条件筛选出符合要求的数据。过滤器使用方括号 [?],后跟过滤条件。考虑以下 JSON 数据:

data = {
    "users": [
        {"name": "Alice", "age": 25},
        {"name": "Bob", "age": 30},
        {"name": "Charlie", "age": 28}
    ]
}

我们想要提取年龄大于 25 岁的用户对象。可以使用以下路径表达式进行过滤:

expression = "users[?age > `25`]"
result = jmespath.search(expression, data)
​
print(result)

输出结果为:

[    {"name": "Bob", "age": 30},    {"name": "Charlie", "age": 28}]

这里,我们使用了过滤器 [?age > 25],表示只选择满足条件的用户对象。

合并操作

JMESPath 还支持合并操作符 [],用于将多个查询结果合并成一个列表。假设我们想要获取所有学生的所有课程名称。可以使用合并操作符 [] 来实现:

data = {
    "students": [
        {
            "name": "Alice",
            "courses": [
                {"name": "Math", "score": 95},
                {"name": "English", "score": 88}
            ]
        },
        {
            "name": "Bob",
            "courses": [
                {"name": "Math", "score": 75},
                {"name": "English", "score": 92}
            ]
        }
    ]
}

获取所有学生的所有课程名称:

expression = "students[].courses[].name"
result = jmespath.search(expression, data)
print(result)

输出结果为:

['Math', 'English', 'Math', 'English']

排序和切片

JMESPath 还支持对查询结果进行排序和切片操作。假设我们想要按学生年龄进行降序排序。可以使用排序函数 sort() 和逆序函数 reverse() 来实现:

data = {
    "students": [
        {"name": "Alice", "age": 20},
        {"name": "Bob", "age": 22},
        {"name": "Charlie", "age": 21}
    ]
}

得到按年龄降序排列的学生列表:

expression = "students | sort_by(@, &age) | reverse(@)"
​
result = jmespath.search(expression, data)
print(result) # [{'name': 'Bob', 'age': 22}, {'name': 'Charlie', 'age': 21}, {'name': 'Alice', 'age': 20}]

切片

data = {
    "fruits": ["apple", "banana", "cherry"]
}

利用切片获取第一个元素

import jmespath
​
data = {
    "fruits": ["apple", "banana", "cherry"]
}
expression = "fruits[0:1]"
result = jmespath.search(expression, data)
​
print(result) # ['apple']

管道

使用管道符号(|),将当前节点的结果传到管道符右侧继续投影。

data = {
    "students": [
        {"name": "Alice", "age": 20},
        {"name": "Bob", "age": 22},
        {"name": "Charlie", "age": 21}
    ]
}

获取所有的姓名:

expression = "students[*].name"
result = jmespath.search(expression, data)
print(result) # ['Alice', 'Bob', 'Charlie']

如果在此基础上想要得到Bob这个值。我们尝试使用索引:

expression = "students[*].name[1]"
result = jmespath.search(expression, data)
print(result) # []

发现执行结果是一个空列表,这个时候怎么办呢?使用管道表达式, <expression> | <expression>

expression = "students[*].name | [1]"

内置函数

计算列表长度

data = {
    "students": [
        {"name": "Alice", "age": 20},
        {"name": "Bob", "age": 22},
        {"name": "Charlie", "age": 21}
    ]
}
​
expression = "length(students)"  # 也可以这样写expression = "students | length(@)"
result = jmespath.search(expression, data)
print(result) # 3

length就是jmespath内置的函数。
当然还有一些其他常用的内置函数,比如:

  • starts_with(str, prefix): 检查字符串是否以指定前缀开头。
  • ends_with(str, suffix): 检查字符串是否以指定后缀结尾。
  • contains(str, substring): 检查字符串是否包含子字符串。
  • length(arr): 返回数组的长度。

最后

jmespath确实很强大,通过逐步学习和实践,可以更好地掌握 JMESPath 的功能和灵活性。

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!

软件测试面试文档

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

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/myh919/article/details/133183668