REST-Assured,接口自动化的 “瑞士军刀“- 断言篇

Hamcrest 是一款用于编写匹配器对象的框架,可以组合创建灵活的匹配器进行断言。

官方网址:http://hamcrest.org/

可以支持 Java、Python、Ruby、Objective-C 等语言

在这里插入图片描述

类似于 TestNG 单元测试框架或者 Junit 单元测试框架中所提供的 Assert 类,比如 TestNG 提供的断言匹配方法:

Assert.assertTrue();
Assert.assertFalse();
Assert.assertEquals();
...

先举几个在 REST-Assured 中用到的较多 Hamcrest 断言匹配方法:

//equalTo:基于传入对象的 equals 方法匹配方式,如果是数组则比较每个元素是否相等。
assertThat("lotto.lottoId", equalTo(5));
//hasItems:测试集合是否包含指定的多个元素
assertThat("lotto.winners.winnerId", hasItems(23, 54));
//...

更多的用法可以参考官方文档示例。

Hamcrest 相比较上述两款单元测试框架自带的断言匹配而言更加强大、优雅、易读。所以 REST-Assured 官方推荐使用的断言匹配就是 Hamcrest。

需要注意的是 REST-Assured 在使用 Hamcrest 的时候需要静态导入:

import static org.hamcrest.Matchers.*;

如果对软件测试、接口、自动化、性能测试、测试开发、面试经验交流。感兴趣可以810119819,群内会有不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。

准备测试环境

我们拿官方文档中的例子来练习,JSON 返回数据如下:

{
"lotto":{
 "lottoId":5,
 "winning-numbers":[2,45,34,23,7,5,3],
 "winners":[{
   "winnerId":23,
   "numbers":[2,45,34,23,3,5]
 },{
   "winnerId":54,
   "numbers":[52,3,12,11,18,22]
 }]
}
}


为了方便我们练习,我们可以使用 PostMan 模拟 Mock,定制我们想要的响应数据(Json/XML)
在这里插入图片描述
以 PostMan 模拟接口 JSON 响应为例,REST-Assured 发起请求:

given().
when().
    get("https://013844de-a0b4-426b-b5dc-dcd3a2e5afe5.mock.pstmn.io/json").
then().
    log().all();

控制台的输出的返回响应结果:

HTTP/1.1 200 OK
Date: Fri, 16 Oct 2020 10:08:18 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: nginx
x-srv-trace: v=1;t=7889c71dfff0bf98
x-srv-span: v=1;s=9305333febed8b23
Access-Control-Allow-Origin: *
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1602842942
ETag: W/"2d1-xSYx3nsyyhHEU4lc3Wu1ZhmyStM"
Vary: Accept-Encoding
Content-Encoding: gzip

{
    "lotto": {
        "lottoId": 5,
        "winning-numbers": [
            2,45,34,23,7,5,3
        ],
        "winners": [
            {
                "winnerId": 23,
                "numbers": [
                    2,45,34,23,3,5
                ]
            },
            {
                "winnerId": 54,
                "numbers": [
                    52,3,12,11,18,22
                ]
            }
        ]
    }
}

JSON 响应断言

需要注意的是 REST-Assured 中的 JSON 响应提取是为 Groovy’s GPath 语法(简称 GPath),而不是 Jayway’s JsonPath 语法。

那么 GPath 到底是什么?以下来自官网的说明

GPath is a path expression language integrated into Groovy which
allows parts of nested structured data to be identified. In this
sense, it has similar aims and scope as XPath does for XML. The two
main places where you use GPath expressions is when dealing with
nested POJOs or when dealing with XML

简单来说 GPath 是一种路径表达式语言,类似于 xpath,GPath 不仅可以应用于 XML,还可以应用于嵌套的层级结构(比如 JSON、HTML)。

Gpath 相比较 Jayway’s JsonPath 语法更为简洁

比如:验证 lottoId 为 5

given().
when().
    get("https://013844de-a0b4-426b-b5dc-dcd3a2e5afe5.mock.pstmn.io/json").
then().
    assertThat().body("json.lotto.lottoId",equalTo(5));

比如:验证 winnerId 为 23 和 54

//前面部分代码跟上述一致,省略
assertThat().body("json.lotto.winners.winnerId",hasItems(23,54));

如果想要断言第一个 winnerId 为 32,我们可以通过索引访问:

assertThat().body("json.lotto.winners.winnerId[0]",equalTo(23));

还可以通过 greatThan 断言大于某个值

assertThat().body("json.lotto.winners.winnerId[0]",greaterThan(20));

复杂的 JsonPath 解析和验证:

  • findAll

筛选符合后面条件的所有项,比如:查找 winnerId 大于 40 的项为 54

assertThat().body("json.lotto.winners.findAll{it.winnerId > 40}.winnerId[0]",equalTo(54));

解释:

findAll{it.winnerId > 40}表示对 winners 集合进行条件筛选,其中 it 表示 winners 本身

由于 findAll 筛选的结果也是集合,所以 winnerId 后面需要加索引

  • find

筛选符合后面条件的第一项

用 find 完成上述的需求:

assertThat().body("json.lotto.winners.find{it.winnerId > 40}.winnerId",equalTo(54));
  • sum

对集合中所有项求和

assertThat().body("json.lotto.winning-numbers.sum()",equalTo(119));

当然也可以和条件筛选结合:

assertThat().body("json.lotto.winners.findAll{it.winnerId > 20}.winnerId.sum()",equalTo(77));
  • max/min

求得集合中最大/最小的项

assertThat().body("json.lotto.winning-numbers.max()",equalTo(45));

如果对软件测试、接口、自动化、性能测试、测试开发、面试经验交流。感兴趣可以810119819,群内会有不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。

XML 响应断言

由于 XML 响应获取指定值也是使用 GPath 的语法来描述的,所以和上述的语法基本一致。

我们还是拿官网的示例来练习,有如下 XML 文件内容:

<shopping>
      <category type="groceries">
        <item>Chocolate</item>
        <item>Coffee</item>
      </category>
      <category type="supplies">
        <item>Paper</item>
        <item quantity="4">Pens</item>
      </category>
      <category type="present">
        <item when="Aug 10">Kathryn's Birthday</item>
      </category>
</shopping>


验证第二个 category 节点的第一个 item 值为 Paper

given().
when().
    get("https://013844de-a0b4-426b-b5dc-dcd3a2e5afe5.mock.pstmn.io/xml").
then().
    assertThat().body("shopping.category[1].item[0]",equalTo("Paper"));

XML 还可以根据属性进行条件筛选,比如选出第一个 type 属性值为 groceries 节点的所有 item 文本

assertThat().body("shopping.category.find{it.@type=='groceries'}.item",hasItems("Chocolate","Coffee"));

有时候我们还可以采用简写:

assertThat().body("shopping.category.findAll{it.@type=='groceries'}",hasItems("Chocolate","Coffee"));

此表达式相比较上述的少了 item,原因在于在 category 节点上将会自动执行 toString()方法,将会获取 category 节点的所有子节点的文本值。

还有些时候我们在写路径的时候由于路径过长,整个表达式过于复杂,我们可以采取类似于 xpath 的相对路径写法,官方命名为深度优先搜索算法,其具体用法是以"**"开头,后面加上条件筛选即可。

比如:上面的例子使用深度优先搜索:

assertThat().body("**.find { it.@type == 'groceries' }",hasItems("Chocolate","Coffee"));

通过 find 找到符合筛选条件的第一个对应节点。

如果对软件测试、接口、自动化、性能测试、测试开发、面试经验交流。感兴趣可以1079636098,群内会有不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值