• 利器 | REST Assured 实践(二):断言实现霍格沃兹测试学院祝您牛年大吉,牛气冲天!


    在上一篇文章中,我们初步探讨了 [REST Assured 的应用实践](http://mp.weixin.qq.com/s?__biz=MzU3NDM4ODEzMg==&mid=2247486810&idx=1&sn=4aa41547a92e761699b99928bc132442&chksm=fd326f91ca45e68713627d612d29fecabf1e1f4c5657a19f72dce47c16b695c1dfbe16ce2a02&scene=21#wechat_redirect),还有很多丰富的用法需要慢慢探索研究。而
    REST Assured 提供的完整断言手段,是测试工程师最常用最重要的功能之一。断言该如何使用呢?

    ** 1. Json 断言**

    1.1 环境准备

    这里以 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.2 JsonPath(Groovy's GPath)

    在 Groovy 的官网,虽然并未提及它在 json 中的使用,但实际上只要是树形的层级关系,无论是 json、xml
    或者其他格式,就可以使用这种简单的语法帮我们去找到其中的值,rest-assured 也已经帮我们实现支持了 GPath 的断言方式

    根节点.子节点
    1)我们可以使用根节点.(点)子节点的方式一层层的找下去,例如我们需要对lottoId等于 5 进行断言:


    @Testvoid 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写法


    @Testvoid 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],写法如下:


    @Testvoid 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


    @Testvoid 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 之间的结果进行断言,具体写法如下:


    @Testvoid 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 默认取匹配到的第一个:


    @Testvoid 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));    }
    

    1.3 实操演示

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


    ** 2. XML断言**

    2.1 环境准备

    上面介绍了,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>
    

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

    2.2 XmlPath断言语法

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


    @Testvoid 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 的数量:


    @Testvoid 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


    @Testvoid testXML(){     when().             get("http://127.0.0.1:8000/restAssured.xml").     then().             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,写法如下:


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

    2.3 实操演示

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


    ** 3. JsonSchema断言**

    3.1 需求背景

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

    • 返回字段较多,无法保证每个字段都写断言

    • 防止客户端未做 null 值的校验判断,如果因为版本变更或网络等原因造成某个不能接收 null 值的返回字段为 null,就很有可能造成软件的崩溃

    • 某些数值是不能为负的

    • 小数点保留位数,对于股票的交易、医疗数据的分析,小数点的精确度都是有其实际价值的

    对返回的字段一个个写断言显然是非常耗时的,这个时候就需要一个模板,可以定义好数据类型和匹配条件,除了关键参数外,其余可直接通过此模板来断言,这个就要请出JsonSchema

    3.2 使用方法

    先对上述的 json 例子做少许修改,增加一个 String 类型的 winnername 字段,这里可以先你不用疑惑为什么加,后续自有其演示作用

    JsonSchema模板生成

    1)首先要借助于Json schema tool的网站https://www.jsonschema.net/,将返回json字符串复制到页面左边,然后点击INFER SHCEMA,就会自动转换为schema json文件类型,会将每个地段的返回值类型都设置一个默认类型; 在pattern中也可以写正则进行匹配

    2)点击“设置”按钮会出现各个类型返回值更详细的断言设置,这个就是schema最常用也是最实用的功能,也可以对每种类型的字段最更细化的区间值校验或者断言,例如长度,取值范围等,具体感兴趣的话可以从官网学习深入学习;平常对重要字段的校验我通常会选用其他断言,比如hamcrest断言

    3)选择复制功能,可以将生成的schema模板保存下来

    rest-assured结合使用

    **
    **

    4)添加maven依赖,在 rest-assured完成支持


    <dependency>    <groupId>io.rest-assured</groupId>    <artifactId>json-schema-validator</artifactId>    <version>4.0.0</version></dependency>
    

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


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

    运行结果:

    多类型校验-Combining schemas
    • String类型的默认值为null,后端很有可能在某个字段无值时返回null,例如我们将之前添加的winnername字段返回null:

    运行查看断言结果:

    很明显用例执行失败,当我们定义了winnernameString类型后,返回null就会断言失败,这显然不符合我们的需求,会造成用例执行结果的误判,这个时候我们需要使winnername即可以为String类型,又可以为null

    这就要用到jsonSchema提供的Combining schemas方法了 Combining schemas提供了如下几种方式:

    • allOf

    • anyOf

    • oneOf

    • not

    这里我们选取anyOf(任何一项满足即可)来完成上述的举例,将原来的type换成Stringnull任何一个都支持的类型:

    再次运行用例,查看断言结果:

    用例完美通过,到此结束~


    ** 4. 推荐阅读**

    断言的语法不止上述列出的这些,但是日常工作中绝大部分需求都可以满足,如有需要可参考官方文档进去研究:
    **
    JsonPath:**
    https://www.javadoc.io/doc/io.rest-assured/json-
    path/latest/io/restassured/path/json/JsonPath.html
    XmlPath:
    https://www.javadoc.io/doc/io.rest-assured/xml-
    path/latest/io/restassured/path/xml/XmlPath.html
    JsonSchema:
    https://json-schema.org/understanding-json-schema/

    另外,在我们实际工作中,很多时候并不是直接对响应结果直接断言,我们可能需要获取响应结果中的某些值,将这些值传递到下一个接口或者和其他接口的响应进行比较断言,这就涉及到了对响应
    response 的获取与处理了,后续文章继续探讨。

    **
    来霍格沃兹测试开发学社,学习更多软件测试与测试开发的进阶技术,知识点涵盖web自动化测试 app自动化测试、接口自动化测试、测试框架、性能测试、安全测试、持续集成/持续交付/DevOps,测试左移、测试右移、精准测试、测试平台开发、测试管理等内容,课程技术涵盖bash、pytest、junit、selenium、appium、postman、requests、httprunner、jmeter、jenkins、docker、k8s、elk、sonarqube、jacoco、jvm-sandbox等相关技术,全面提升测试开发工程师的技术实力
    QQ交流群:484590337
    公众号 TestingStudio
    点击获取更多信息

    **》2021 假期充电,
    来霍格沃兹测试开发学社,学习更多软件测试与测试开发的进阶技术,知识点涵盖web自动化测试 app自动化测试、接口自动化测试、测试框架、性能测试、安全测试、持续集成/持续交付/DevOps,测试左移、测试右移、精准测试、测试平台开发、测试管理等内容,课程技术涵盖bash、pytest、junit、selenium、appium、postman、requests、httprunner、jmeter、jenkins、docker、k8s、elk、sonarqube、jacoco、jvm-sandbox等相关技术,全面提升测试开发工程师的技术实力
    QQ交流群:484590337
    公众号 TestingStudio
    点击获取更多信息

  • 相关阅读:
    JavaScript与C# Windows应用程序交互
    用DateTime.ToString(string format)输出不同格式的日期
    时间间隔与暂停
    C#中比较两个时间的时间差
    lambda函数的用法
    Tornado笔记
    DjangoWeb应用开发实战笔记
    再看装饰器
    描述符
    flask简单代码回顾
  • 原文地址:https://www.cnblogs.com/hogwarts/p/15786973.html
Copyright © 2020-2023  润新知