接口自动化 - 接口组合业务练习(CRUD组合)-REST-assure(Java版)

文章目录

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

编程真是一件很奇妙的东西。你只是浅尝辄止,那么只会觉得枯燥乏味,像对待任务似的应付它。但你如果深入探索,就会发现其中的奇妙,了解许多所不知道的原理。知识的力量让你沉醉,甘愿深陷其中并发现宝藏。



本文开始

1. 需求分析

接口自动化整体思路构建

1.1 业务需求分析

明确被测产品:petstore系统 - 宠物管理。

宠物商店接口文档:Swagger文档

宠物管理业务场景:

1.添加宠物。

2.查询宠物信息。

3.修改宠物信息。

4.删除宠物。

1.2 编写自动化脚本思路

2. 接口自动化脚本编写

  1. 首先编写CRUD单一接口,保证单一接口跑通,然后考虑业务接口组合优化,和跑通;
  2. 接口逻辑和业务逻辑可以分开

【注】

1.请求中不添加 contentType(ContentType.JSON) 会导致请求失败

2.因为HTTP协议需要明确的Content-Type标头来告诉服务器如何处理请求体。

  • asString() 和 toString() 在RestAssured中有重要区别
    1.asString(): 将HTTP响应体内容作为字符串返回
    如:asString() 返回:{"id": 1, "name": "John"}
    2.toString(): 返回Body对象的字符串表示,通常是对象本身的描述信息
    如:输出类似:io.restassured.internal.RestAssuredResponseImplBody2@1a2b3c4d

编写CRUD基础接口代码-保证每个接口测试通过

java 复制代码
/**
 * 新增-接口方法 POST
 *  url: https://petstore.swagger/pet
 */
public void add() {
	//构造请求体参数
    String newPet = "{\"id\":"+petId+",\"category\":{\"id\":0,\"name\":\"string\"},\"name\":\""+
            newPetName+"\",\"photoUrls\":[\"string\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
    given()
        .contentType(ContentType.JSON)
        .body(newPet)
        .log().all()
    .when()
        .post(baseURL)
    .then()
        .log().all();
}

/**
 * 新增方法:忽略HTTPS校验
 */
public void add2() {
    String newPet = "{\"id\":"+petId+",\"category\":{\"id\":0,\"name\":\"string\"},\"name\":\""+
            newPetName+"\",\"photoUrls\":[\"string\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
    given()
        //忽略HTTPS校验
        .relaxedHTTPSValidation()
        .contentType(ContentType.JSON)
        .body(newPet)
        .log().all()
    .when()
        .post(baseURL)
    .then()
        .log().all();
}

/**
 * 查看-接口方法 GET
 *  url: https://petstore.swagger/findByStatus?status=available
 */
public String get() {
    HashMap<String, Object> statusQuery = new HashMap<>();
    statusQuery.put("status", "available");
    String body = given()
        .queryParams(statusQuery)
        .log().all()
    .when()
        .get(baseURL + "/findByStatus")
    .then()
        .log().all()
        .extract().response()
        .getBody().asString();
    System.out.println(body);
    return body;
}

/**
 * 更新-接口方法 PUT
 *  url:  https://petstore.swagger/pet
 */
public void update() {
    String updatePet = "{\"id\":"+petId+",\"category\":{\"id\":0,\"name\":\"string\"},\"name\":\""+
            updatePetName+"\",\"photoUrls\":[\"string\"],\"tags\":[{\"id\":0,\"name\":\"string\"}],\"status\":\"available\"}";
    given()
        .contentType(ContentType.JSON)
        .body(updatePet)
        .log().all()
    .when()
        .post(baseURL)
    .then()
        .log().all();
}

/**
 * 删除-接口方法 DELETE
 *  url: https://petstore.swagger/pet/petId
 *   删除参数是在路径上,直接拼接到url上
 */
public void delete() {
    given()
        .log().all()
    .when()
        .delete(baseURL + "/" + petId)
    .then()
        .log().all();
}

测试用例业务逻辑执行:

java 复制代码
/**
 * 新增宠物测试用例
 *  执行业务逻辑:先新增,再查看验证
 */
@Order(12)
@Test
public void addTest() {
    //新增
    add();
    //查看
    String body = get();
    //校验
    DocumentContext context = JsonPath.parse(body);
    List<Long> ids = context.read("$..id");//或者使用$[*].id
    List<String> names = context.read("$..name");
    List<String> status = context.read("$..status");//$[*].status

//        System.out.println(status);
    assertAll(
        () -> assertThat(status, everyItem(equalTo("available"))),
        () -> assertThat(ids, Matchers.hasItem(Long.valueOf(petId))),
        () -> assertThat(names, Matchers.hasItem(newPetName))
    );
}

/**
 * 修改宠物测试用例
 */
@Order(13)
@Test
public void updateTest() {
    //修改宠物
    update();
    //查看修改
    String body = get();
    //断言
    DocumentContext context = JsonPath.parse(body);
    List<Long> ids = context.read("$..id");//或者使用$[*].id
    List<String> names = context.read("$..name");
    assertAll(
        //验证每一个status,都等于available
        () -> assertThat(ids, Matchers.hasItem(Long.valueOf(petId))),
        () -> assertThat(names, Matchers.hasItem(updatePetName))
    );
}

/**
 * 删除宠物测试用例
 */
@Order(14)
@Test
public void deleteTest() {
    //删除宠物
    delete();
    //查询删除结果
    String body = get();
    //断言
    DocumentContext context = JsonPath.parse(body);
    List<Long> ids = context.read("$..id");//或者使用$[*].id
    assertAll(
        //ids,都不等于petId
        () -> assertThat(ids, not(Matchers.hasItem(Long.valueOf(petId))))
    );

}

断言说明:

assertAll 是JUnit 5的特性,它允许同时执行多个断言,即使前面的断言失败,也会继续执行后面的断言,最后报告所有失败。

java 复制代码
assertAll(
      () -> assertThat(status, everyItem(equalTo("available"))),
      () -> assertThat(ids, Matchers.hasItem(Long.valueOf(petId))),
      () -> assertThat(names, Matchers.hasItem(newPetName))
);

1.检查status列表中的每个元素都等于"available"

everyItem():Hamcrest匹配器,表示"每一个元素"

equalTo("available"):匹配器,表示"等于 available"

2.检查ids列表中是否包含转换后的petId

Long.valueOf(petId):将字符串转换为Long

hasItem():Hamcrest匹配器,表示"包含某个元素"

2.3 优化

提取公共参数

java 复制代码
@BeforeAll
public static void beforeAll() {
     //公共URL提取
     baseURL = "https://petstore.swagger/pet";
     //提取需要提前设置的传递参数,这里简单构造,后续data数据参数化
     petId = "123456123456";
     newPetName = "newPet";
     updatePetName = "updatePet";
     //配置代理地址
//   RestAssured.proxy = host("127.0.0.1").withPort(8888);
 }

配置代理查看接口数据:

出现接口问题,不知道如何处理-使用代理查看接口数据

操作步骤:

1.请求前BeforeAll中:配置代理信息

java 复制代码
RestAssured.proxy = host("127.0.0.1").withPort(8888);

2.given()中忽略https校验:

java 复制代码
given().relaxedHTTPSValidation()

【注】接口发送到服务端前,拦截请求,发送到代理工具上,查看具体信息是否正确,然后再将接口发送到服务端;接口→代理工具→服务端

设置用例排序执行-Junit5配置

用例排序执行步骤:

1.test/resources目录下创建:junit-pltform.properties文件(文件名自定义)

配置如下设置:

yaml 复制代码
junit.jupiter.testmethod.order.default=org.junit.jupiter.api.MethodOrderer$OrderAnnotation

2.在测试用例中使用注释@Order()指定顺序使用即可

数字小的先执行

生成测试Allure报告

文件中导入.allure文件

通过mvn命令生成

mvn clean test -Dtest=测试类路径 allure:report

mvn allure:serve


总结

✨✨✨各位读友,本篇分享到内容是否更好的帮助你理解,如果对你有帮助给个👍赞鼓励一下吧!!
🎉🎉🎉世上没有绝望的处境,只有对处境绝望的人。
🎉🎉🎉一遇挫折就灰心丧气的人,永远是个失败者。而一向努力奋斗,坚韧不拔的人会走向成功。
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!!

相关推荐
云原生指北1 小时前
GitHub Copilot SDK 入门:五分钟构建你的第一个 AI Agent
java
Leinwin6 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
2401_865382506 小时前
信息化项目运维与运营的区别
运维·运营·信息化项目·政务信息化
漠北的哈士奇6 小时前
VMware Workstation导入ova文件时出现闪退但是没有报错信息
运维·vmware·虚拟机·闪退·ova
薛定谔的悦6 小时前
MQTT通信协议业务层实现的完整开发流程
java·后端·mqtt·struts
如意.7596 小时前
【Linux开发工具实战】Git、GDB与CGDB从入门到精通
linux·运维·git
enjoy嚣士6 小时前
springboot之Exel工具类
java·spring boot·后端·easyexcel·excel工具类
运维小欣6 小时前
智能体选型实战指南
运维·人工智能
罗超驿6 小时前
独立实现双向链表_LinkedList
java·数据结构·链表·linkedlist
yy55276 小时前
Nginx 性能优化与监控
运维·nginx·性能优化