利器 | REST Assured 实践(二):断言实现

举报
ceshiren 发表于 2022/04/02 15:53:55 2022/04/02
【摘要】 在上一篇文章中,我们初步探讨了 REST Assured 的应用实践,还有很多丰富的用法需要慢慢探索研究。而 REST Assured 提供的完整断言手段,是测试工程师最常用最重要的功能之一。断言该如何使用呢?这里以 rest-assured 官方给的一个示例做演示学习{"lotto":{ "lottoId":5, "winning-numbers":[2,45,34,23,7,5,3],...


在上一篇文章中,我们初步探讨了 REST Assured 的应用实践,还有很多丰富的用法需要慢慢探索研究。而 REST Assured 提供的完整断言手段,是测试工程师最常用最重要的功能之一。断言该如何使用呢?

这里以 rest-assured 官方给的一个示例做演示学习

{
"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]
                 }]
                 }
                 }

在本地使用 python -m CGIHTTPServer 临时搭建起一个服务:
根节点.子节点
1)我们可以使用根节点.(点)子节点的方式一层层的找下去,例如我们需要对lottoId等于 5 进行断言:

                 @Test
                 void testGPath(){
                      given().when().log().all().get("http://127.0.0.1:8000/restAssured.json").then().log().all().body("lotto.lottoId",equalTo(5));
                                                           }

2)如果我们想要断言winners数组下面的winnerId,检查23和54是否包含其中,可以如下lotto.winners.winnerId写法

                                                           @Test
                                                           void testGPath(){
 given().when().log().all().get("http://127.0.0.1:8000/restAssured.json").then().log().all().body("lotto.winners.winnerId",hasItems(54,23));
           }

索引取值
1)如果我们想要取某些相同字段中的某一个,可以使用类似索引的方式获取,例如想要断言 winners 数组下面的 winnerId 的第一个值是否为23,可以使用 lotto.winners.winnerId[0],写法如下:

                                                                                                           @Test
                                                                                                           void testGPath(){
                     given().when().log().all().get("http://127.0.0.1:8000/restAssured.json").then().log().all().body("lotto.winners.winnerId[0]",equalTo(23));
                                                    }

2)如果我们想要取某些相同字段中的最后一个,可以使用 -1 作为索引,例如断言断言 winners 数组下面的 winnerId 的最后一个的值是否为 54

    @Test
      void testGPath(){
               given().when().log().all().get("http://127.0.0.1:8000/restAssured.json").then().log().all().body("lotto.winners.winnerId[-1]",equalTo(54));
                                                }

findAll
有时候我们需要获取符合某些条件的结果来进行断言,这里 findAll 可以帮助我们实现,我们可以在 findAll 方法中写筛选条件,例如我们想取 winnerId 的值在大于或等于 30 小于 60 之间的结果进行断言,具体写法如下:

  @Test
                                                                                                   void testGPath(){
                  given().when().log().all().get("http://127.0.0.1:8000/restAssured.json").then().log().all().body("lotto.winners.findAll{ winners -> winners.winnerId >= 30 && winners.winnerId < 60}.winnerId[0]",equalTo(54));
           }

find
find 的用法与 findAll 基本一致,只是 find 默认取匹配到的第一个:

                                                                                               @Test
                                                                                                     void testGPath(){
                        given().when().log().all().get("http://127.0.0.1:8000/restAssured.json").then().log().all().body("lotto.winners.find{ winners -> winners.winnerId >= 30 && winners.winnerId < 60}.winnerId",equalTo(54));
                                                     }

将上述各个断言语法写在一起,实际运行校验结果:
上面介绍了,GPath 也支持 XML 格式的断言,这里再以 rest-assured 官方给的一个实例做演示

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

再次在本地搭起一个临时服务:

若我们要对第二个 name 的值 Coffee 进行断言,写法如下:

    @Test
     void testXML(){
         when().get("http://127.0.0.1:8000/restAssured.xml").then().log().all().body("shopping.category[0].item[1].name",equalTo("Coffee"));
                                                                         }

size()
可以利用 size() 方法来获取对应节点的数量,例如这里要断言 category 的数量:

                                                                                                  @Test
                void testXML(){
        when().get("http://127.0.0.1:8000/restAssured.xml").then().log().all().body("shopping.category.size()",equalTo(3));
                      }

it.@type、it.price
在 xml中 断言中,可以利用 it. 属性或节点的值来作为筛选条件;
例如这里要获取 type 为 supplies 的 category 下的第一个 item 的 name,以及获取 price 为 10 的商品名 name。

                                                                                                                @Test
                                                                                                                   void testXML(){
                                 when().get("http://127.0.0.1:8000/restAssured.xml").hen().log().all().body("shopping.category.findAll{ it.@type == 'supplies' }.item[0].name",equalTo("Paper")).body("shopping.category.item.findAll{ it.price == 10 }.name",equalTo("Chocolate"));
                                                                                                  }

.findAll
对于xml中有一个特别的语法,
.findAll,可以直接忽略前面的节点,直接对筛选条件进行匹配,依然获取price为10的商品名name,写法如下:

                                              @Test
                                                   void testXML(){
              when().get("http://127.0.0.1:8000/restAssured.xml").then().log().all().body("**.findAll{ it.price == 10 }.name",equalTo("Chocolate"));
                        }

将上述各个断言语法写在一起,实际运行校验结果:

在实际工作中,对接口返回值进行断言校验,除了常用字段的断言检测以外,还要对其他字段的类型进行检测,原因在于:

  • 返回字段较多,无法保证每个字段都写断言
  • 防止客户端未做 null 值的校验判断,如果因为版本变更或网络等原因造成某个不能接收 null 值的返回字段为 null,就很有可能造成软件的崩溃
    某些数值是不能为负的
  • 小数点保留位数,对于股票的交易、医疗数据的分析,小数点的精确度都是有其实际价值的
    对返回的字段一个个写断言显然是非常耗时的,这个时候就需要一个模板,可以定义好数据类型和匹配条件,除了关键参数外,其余可直接通过此模板来断言,这个就要请出JsonSchema了
    先对上述的 json 例子做少许修改,增加一个 String 类型的 winnername 字段,这里可以先你不用疑惑为什么加,后续自有其演示作用
    1)首先要借助于Json schema tool的网站https://www.jsonschema.net/,将返回json字符串复制到页面左边,然后点击INFER SHCEMA,就会自动转换为schema json文件类型,会将每个地段的返回值类型都设置一个默认类型; 在pattern中也可以写正则进行匹配
    2)点击“设置”按钮会出现各个类型返回值更详细的断言设置,这个就是schema最常用也是最实用的功能,也可以对每种类型的字段最更细化的区间值校验或者断言,例如长度,取值范围等,具体感兴趣的话可以从官网学习深入学习;平常对重要字段的校验我通常会选用其他断言,比如hamcrest断言
    3)选择复制功能,可以将生成的schema模板保存下来
    4)添加maven依赖,在rest-assured完成支持
                                                                                      <groupId>io.rest-assured</groupId>
                                      <artifactId>json-schema-validator</artifactId>
                                                    <version>4.0.0</version>
                                                    </dependency>

5)使用matchesJsonSchemaInClasspath方法对响应结果进行schema断言

                                               @Test
                                                void jsonSchemaTest(){
                                                     get("http://127.0.0.1:8000/restAssured.json").
                                                               then().log().all()
                          .body(matchesJsonSchemaInClasspath("jsonSchema.json"));
                      }

运行结果:

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。