jck28-lucio-【实战】电子商城接口自动化测试框架实战

现有问题

  • 可维护性差:一个 api 发生变化,需要修改用例文件
  • 可读性差:无法从代码中看出来明确的业务逻辑
  • 断言能力差:响应内容只能一层一层提取

接口自动测试架构优化

  • 接口信息
  • 测试用例
    @startuml
    scale 800*500

package utils <> {
class Log
}

package apis <> {
class BaseApi
note bottom of BaseApi: api 的公共封装:日志封装,log封装配置以及其他公共的使用
class CartApi
note bottom of CartApi: 具体的业务接口,只记录接口相关信息
}

package testcases <> {
class CartTest
class 其他Test
}
note bottom of testcases: 测试用例包含业务步骤与断言,不会实现具体的接口信息

’ note top of testcases: 测试用例: 包含 测试步骤、测试用例等
@enduml

接口自动化测试框架优化

  • 输入信息(model)
  • 接口信息(api)
  • 测试用例(testcase)
    输入信息表示接口请求过程中和业务相关的具体数据信息

商品模型

@startuml
scale 100
class Cart {
Integer goodsId
Integer number
Integer productId
void create()
void delete()
void update()
void get()
}
@enduml

Model 的表现形式

示例

// 简单场景输入
public void detele(Integer id){

}

// 正常场景示例-定义
public class CartModel {

private Integer goodsId;
private Integer number;
private Integer productId;
// 示例代码省略getter setter
// 真实场景需要添加

}

// 正常场景示例-使用
CartModel cartModel = new CartModel();
cartModel.setNumber(1);
cartModel.setGoodsId(1057036);
cartModel.setProductId(71);

实体类转换为 JSON

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.13.1</version>
</dependency>

UserModel userModel = new UserModel();
ObjectMapper mapper = new ObjectMapper();
try {
    String Json =  mapper.writeValueAsString(userModel);
    System.out.println(Json);
} catch (JsonProcessingException e) {
    e.printStackTrace();
}

JSON 快速转换实体类(选修)

  • IDEA插件:
    • GsonFormatPlus
    • LomBok
org.projectlombok lombok 1.18.8

什么是过滤器

participant requests as req
participant response as res
participant filter

scale 1000*700

group 未使用过滤器
req ↔ res: 发起请求获得相应
end

group 使用过滤器
req → filter: 请求发起之前,拼装好请求信息,\n 经过过滤器,过滤器处理之后发起真实的请求。
filter → res: 过滤器先拿到真实的响应信息,处理之后再返回。
end

过滤器的使用场景

所有的公共配置

  • 日志信息
  • 请求头配置

过滤器的使用

  • 定义:
    • 实现 Filter 接口,重写 filter 方法(请求信息,响应信息,过滤器信息)
  • 使用:
    • given().filter(重写的filter实例)
public class DemoFilter implements Filter {
    
    @Override
    public Response filter(FilterableRequestSpecification filterableRequestSpecification,
                           FilterableResponseSpecification filterableResponseSpecification,
                           FilterContext filterContext) {

        // 设置基地址
        filterableRequestSpecification.baseUri("基地址");
        filterableRequestSpecification.contentType("application/json");
        // 发起真实请求
        Response response = filterContext.next(filterableRequestSpecification, filterableResponseSpecification);
        // 拼接请求信息
        String requests_info = filterableRequestSpecification.getMethod() + " "
                + filterableRequestSpecification.getURI()
                + "\n Request Body =>"
                + filterableRequestSpecification.getBody();

        log.debug("接口请求日志:" + requests_info);
        // 在 allure 中添加日志信息
        addAttachment(filterableRequestSpecification.getBasePath() + "接口请求:", requests_info);
        String response_info =
                "\n Response Status => "
                        + response.getStatusCode()
                        + " " + response.getStatusLine()
                        + "\n Response Body => " + response.getBody().asPrettyString();
        addAttachment(filterableRequestSpecification.getBasePath() + "接口响应:", response_info);
        log.debug("接口响应日志:" + response_info);
        return response;
    }

}

日志配置

Logger log = LoggerFactory.getLogger("litemall");
}
<pattern>
<!--                优雅的日志格式-->
    %d{dd-MM-yyyy HH:mm:ss.SSS} %highlight(%-5level) %magenta([%thread]) %yellow(%logger{40}.%M\(%class{0}.java:%line\)) - %msg%throwable%n
</pattern>