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

发表于:2021-12-21 09:12

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:软件测试狂阿沐    来源:CSDN

  Hamcrest 是一款用于编写匹配器对象的框架,可以组合创建灵活的匹配器进行断言。
  官方网址:http://hamcrest.org/
  可以支持 Java、PythonRuby、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 找到符合筛选条件的第一个对应节点。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号