接口自动化测试 - REST-assure小练习(Java版-分层)

文章目录

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

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



本文开始

1. 自动化前准备

1.需求分析:对自动化前的需求进行详细分析

2.接口测试用例设计

3.编写接口自动化测试脚本

保证单接口自动化通过;再考虑业务流程自动化测试(组合接口测试);

【注】当前利用AI辅助,使用智能体辅助,极大降低自动化代码编写难度;

2. 接口自动化分层

接口自动化框架设计:

封装 + 分层+ 接口实现和测试用例以及断言进行拆分

yaml 复制代码
├── apis
│   ├── base_api
│   ├── department
│   └── wework
├── config
│   └── config.yaml
├── tests
│   ├── test_departments
│   └── test_department_flow
└── utils
    ├── log_utils
    └── utils

apis包下:可以划分多个功能模块

如:department中封装某个接口的增删改查方法,还可以有多个这样的模块;

tests包下:测试主逻辑 + 断言

config包下:配置公共变量,用于切换不同环境

如:提取公共BaseURL,请求参数等

参数可以封装到类中,直接根据类中方法获取想要的参数;

分层 作用 示例
base_api 封装和接口框架直接相关的方法 接口请求封装
wework 封装业务的全局操作 获取 token;获取配置数据
department 封装子模块的操作 部门信息的增删改查
test_department 测试步骤、业务流程及断言 添加部门用例

实际项目结构自己根据需求自定义:

示例:

3.接口自动化代码实现

封装单模块业务全局操作

创建一个功能模块的父类,封装业务该模块功能的公共方法;

如果是多个模块有公共方法,可以封装到baseApi方法中,让子类继承即可;

如下述是企业部门模块功能公共方法封装

java 复制代码
/**
 * 封装业务的全局操作
 *  获取 token;
 *  获取配置数据
 */
public class WeWork {
    String corpid;
    ConfigEntity configEntity;
    public WeWork() {
        configEntity = ConfigUtil.getConfig();
        corpid = "sws37f7dsdd8sdb17ac";
        //使用静态变量封装一个值,这样下述请求中不需要写公共的BaseUrl
        //为当前测试会话中的所有 HTTP 请求设置统一的、基础的 URL 前缀。
        RestAssured.baseURI = configEntity.getBaseUrl();
    }

    /**
     * 获取token
     * @param secret
     * @return
     */
    String getToken(String secret) {

        Response response = given()
            //获取请求的日志 参数信息 请求头 请求参数
            .log().all()
            .param("corpid", corpid)
            .param("corpsecret", secret)
        .when()
            .get("/gettoken")
        .then()
            //获取响应日志 响应body 响应头信息
            .log().all()
            .extract().response();
        return response.path("access_token").toString();
    }

}

封装单模块下子模块的具体业务操作

封装部门下具体业务接口操作:

如:封装部门信息的增删改查,封装具体业务逻辑操作:只负责操作,不关心结果;

java 复制代码
/**
 * 与部门相关的操作:创建部门,删除部门,查询部门
 *  接口请求CRUD逻辑
 */
public class WeWorkDepartment extends WeWork{
    String secret;
    public WeWorkDepartment() {
        secret = configEntity.getContactsSecret();
    }

    /**
     * 创建部门方法
     * @param createEntity
     *  -请求体中的参数使用类来表示
     *   调用者可以通过直接看实体类知道需要的参数
     */
    public Response createDepartment(DepartmantCreateEntity createEntity) {

        Response response = given()
            .body(createEntity)
            // 设置请求的内容类型为 JSON,并指定字符编码为 UTF-8
            .contentType(ContentType.JSON.withCharset(StandardCharsets.UTF_8))
            .log().all()
        .when()
            .post("/department/create?access_token=" + getToken(secret))
        .then()
            .log().all()
            .extract().response();
        return response;
    }

    /**
     * 删除接口方法
     */
    public Response delete(Integer depId) {
        Response response = given()
            .param("id", depId)
        .when()
            .post("/department/delete?access_token=" + getToken(secret))
        .then()
            .extract().response();
        return response;
    }

    /**
     * 查询ID
     */
    public List<Integer> getIds() {
        String dpsText = given()
        .when()
            .post("/department/simplelist?access_token=" + getToken(secret))
        .then()
            .extract().response().getBody().asString();
        return JsonPath.read(dpsText, "$..id");
    }


}

子模块业务的测试用例封装

子模块测试用例关注:测试步骤、业务流程及断言

java 复制代码
**
 * 测试用例: 主要关注业务逻辑,与用例输入和输出
 */
public class DepartmentApiObjectTest {
    static WeWorkDepartment weWorkDepartment;
    static WeworkMember weworkMember;

    /**
     * 前置处理-初始化对象
     */
    @BeforeAll
    static void setUp() throws IOException {
        weWorkDepartment = new WeWorkDepartment();
        weworkMember = new WeworkMember();
    }

    /**
     * 参数化设置
     */
    @ParameterizedTest
    @MethodSource("util.TestDataFactory#getDepartmentCreateTestData")
    void createDepartmentParams(DepartmantCreateEntity departmantCreateEntity) {
        Response re = weWorkDepartment.createDepartment(departmantCreateEntity);

    }

    /**
     * 测试用例业务逻辑实现
     *  新增存在的部门
     */
    @Test
    void createDepartmentExist() {
        //1.准备已存在的部门
        DepartmantCreateEntity createDepartment = new DepartmantCreateEntity("技术部","zs",1,1,1 );
        weWorkDepartment.createDepartment(createDepartment);
        //2.有存在部门情况下,创建相同信息部门失败
        Response response = weWorkDepartment.createDepartment(createDepartment);
        MatcherAssert.assertThat(response.path("errcode"),is(60020));
        //3.删除部门
        weWorkDepartment.delete(createDepartment.getId());
        //4.查询部门删除成功
        List<Integer> ids = weWorkDepartment.getIds();
        MatcherAssert.assertThat(ids, not(hasItem(createDepartment.getId())));
        //5.再次创建部门
        weWorkDepartment.createDepartment(createDepartment);
        //6.查询部门创建成功
        ids = weWorkDepartment.getIds();
        assertThat(ids, hasItem(createDepartment.getId()));
    }
}

优化

全局公共参数/变量提取

config-test.yaml文件中封装需要参数

xml 复制代码
# 读取参数的配置文件
baseUrl: https://xxx.com
corpId: xxxx
contactsSecret: xxx

配置参数实体类:

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ConfigEntity {
    private String baseUrl;
    private String corpId;
    private String contactsSecret;
}

读取yaml文件,yaml文件中包含提取的参数

java 复制代码
/**
 * 配置读取yaml文件的工具类
 */
public class ConfigUtil {
    public static ConfigEntity getConfig() {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        try {
            //读取yaml文件并反序列化
            return mapper.readValue(ConfigEntity.class.getClassLoader()
                    .getResourceAsStream("config-test.yaml"), ConfigEntity.class);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }
}

封装后使用示例:

java 复制代码
ConfigEntity configEntity = ConfigUtil.getConfig();
RestAssured.baseURI = configEntity.getBaseUrl();

其他优化考虑:

1.多环境切换配置:考虑生产环境,测试环境等

2.数据库配置:读取数据库数据作为数据源进行参数化测试

3.响应断言:面对复杂响应情况,多层嵌套响应,做出响应优化;

4.可以考虑参数化-使用Junit5方法

小技巧

1.封装参数:选择Map 或 类;如:请求体参数

推荐类封装参数,使用类让其他使用者调用,直接查看类就知道参数是什么;

2.如果用例数量很多,成千上万,怎么维护和保证运行效率?

维护:来源前期代码规范,接口自动化脚本编写有较好的约定 ,抽象,前期规范到位,后期容易维护;

运行效率:在保证接口用例之间没有资源争夺情况下,可以考虑使用多线程运行脚本;


总结

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

相关推荐
weixin_438077492 分钟前
CS336 Assignment 4 (data): Filtering Language Modeling Data 翻译和实现
人工智能·python·语言模型·自然语言处理
小郭团队3 分钟前
未来PLC会消失吗?会被嵌入式系统取代吗?
c语言·人工智能·python·嵌入式硬件·架构
yesyesido3 分钟前
智能文件格式转换器:文本/Excel与CSV无缝互转的在线工具
开发语言·python·excel
_200_6 分钟前
Lua 流程控制
开发语言·junit·lua
环黄金线HHJX.6 分钟前
拼音字母量子编程PQLAiQt架构”这一概念。结合上下文《QuantumTuan ⇆ QT:Qt》
开发语言·人工智能·qt·编辑器·量子计算
王夏奇6 分钟前
python在汽车电子行业中的应用1-基础知识概念
开发语言·python·汽车
子夜江寒7 分钟前
基于PyTorch的CBOW模型实现与词向量生成
pytorch·python
He_Donglin7 分钟前
Python图书爬虫
开发语言·爬虫·python
北辰当尹8 分钟前
【实习之旅】Kali虚拟机桥接模式ping通百度
java·服务器·桥接模式
天远Date Lab11 分钟前
Python金融风控实战:集成天远多头借贷行业风险版API实现共债预警
大数据·python