软件测试 | json响应断言

120 阅读1分钟

1.json响应断言简介

前面的内容已经简单介绍了如何断言验证接口的响应值。在实际工作中,获取的json响应倪荣荣往往十分复杂,面对复杂的json响应体,可以用JSONPath对其进行解析。JSONPath提供了强大的解析json的功能,可以更便捷、灵活地解析json内容。

2.json响应断言环境准备

Python版本

pip install jsonpath

Java版本

<dependency>
    <groupId>com.jayway.jsonpath</groupId>
    <artifactId>json-path</artifactId>
    <version>2.6.0</version>
</dependency>

3.XPath和JSONPath语法

XPath和JSONPath语法有很多似之处,但还是有所不同。表7-1是XPath和JSONPath语法的对比。

XPathJSONPath描述
/$根节点对象/元素
.@当前的对象/元素
/.or[]匹配下级元素
..n/a匹配上级元素,JSONPath不支持
//..递归方式匹配所有子元素
**通配符,匹配所有对象/元素,无论其名称如何
@n/a访问属性
[][]下标运算符,JSONPath从0开始
[,]连接的操作符,多个结果拼接成列表返回
[]?()过滤器(脚本)表达式
n/a()脚本表达式,使用基础脚本引擎

注:表中的一些语法符号相同,但作用是不一样的具体见表中的描述。

下面是一组json结构数据,分别通过JSONPath和XPath的方式提取出来。

{
 "store":{
   "book":[
   {
      "category":"reference",
      "author":"Nigel Ress",
      "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
   }
 }
}

表7-2列出了XPath与XPath与JSONPath表达式的对比。

XPathJSONPath结果
/store/book/author$.store.book[*].authorstore中所有book的author
//author$..author所有的author
/store/$.store.*store中所有元素
/store//price$.store..pricestore中所有的price
//book[3]$..book[2]book列表中的第三个
//book[last()]$..book[-1:]book列表中的倒数第一个
//book[position()<4]$..book[:3]book列表中的前两个
//book[isbn]$..book[?(@.isbn)]所有有isbn的book
//book[price<10]$..book[?(@.peice<10)]所有价格低于10元的书
//*$..*所有json结构体中的元素

实例:想要获取store目录下的第一本书title

(1)XPath中的语法是:

/store/book[0]/title

(2)JSONPath的语法是:

$.s ore.book[0].itle
$['store']['book'][0]['title']

4.实战练习

以下是ceshiren.com/t/topic/695…这个接口的正常响应数据(因响应数据过大,删除了部分内容):

{
 'pos _stream':{
    'posts':[
      {
        'id':17126,
        'name':'思寒',
        'username':'seveniruby',
        'avatar_template':'/user_avatar/ceshiren.com/seveniruby/{size}/2_2.png',
        'created_at':'2020-10-02T04:23:30.586z',
        'cooked':'<p>一直以来的平均涨薪率在30%以上,这次刷新的记录估计要保持好几年了</p>'
        'post_number':6,
        'post_type':1,
        'updated_at':'2020-10-02T04:23:48.775z',
        'reply_to_post_number':None,
        'reads':651,
        'readers_count':650,
        'score':166.6,
        'yours':False,
        'topic_id':6950,
        'topic_slug':'topic',
        'display_username':'思寒',
        'primary_group_name':'python_12',
        //省略 
      },
    ],
 },
 'timeline_loolup':,
 'suggested_topics':,
 'tags':[
   '精华帖',
   '测试开发',
   '测试求职',
   '测试外包',
 ],
 'id'=6950,
 'title':'测试人生 | 从外包菜鸟到测试开发,薪资一年翻三倍,连自己都不相信!(附面试真题与答案)''fancy_title':'测试人生 | 从外包菜鸟到测试开发,薪资一年翻三倍,连自己都不敢信!(附面试真题与答案)',
}

通过使用JSONPath表达式获取以上响应内容中name字段为“思寒”所对应的cooked,且其中也包含“涨薪”的数据,并且做断言。

(1)Python演示代码

使用JSONPath表达式实现断言

import requests
from jsonpath import jsonpath
r = requests.get("https://ceshiren.com/t/topic/6950.json").json()
result = jsonpath(r, "$..posts[?(@.name == '思寒')].cooked")[1]
assert " 涨薪 " in result

(2)Java演示代码

使用JSONPath表达式实现断言

import com.jayway.jsonpath,jsonpath;
import org.junit.jupiter.api.Test;
import java.util.List;
import static io.restassured.RestAssured.given;
public class jsonTest{
    
    @Test
    void jsonTest(){
       //获取响应信息,并转成字符串类型
       String res = given().when().
              get("https://ceshiren.com/t/topic/6950.json")
              .then().extract().response().asString();
       //通过JSONPath表达式提取需要的字段
       List<String> result = JsonPath.read(res. "$..posts[?(@.name == '思寒')].cooked");
       //断言验证
       assert result.get(1).contains("涨薪");
    }
}

搜索微信公众号:TestingStudio霍格沃兹的干货都很硬核