打造全方位接口自动化测试平台:自动获取接口信息功能实现

目前正在着手开发一款功能全面的接口自动化测试平台,该平台将涵盖登录、用户管理、权限控制、项目管理、用例管理、测试数据管理、测试报告生成、任务调度、缺陷跟踪以及系统配置等多个核心模块。为了方便编写测试用例,我们需要通过一些方式来自动获取接口信息,如读取接口文档、调用Swagger接口等方式。本篇内容主要介绍一下通过Swagger接口和Swagger2.0文件来自动化获取接口信息。

在这里插入图片描述

通过Swagger获取接口信息详解

技术选型

  • 后端:采用Java作为主要开发语言。
  • 前端:使用VUE框架进行界面展示。
  • SwaggerParser:SwaggerParser是Swagger官方出的Swagger格式解析工具。

数据库表设计

我们需要设计3张表,项目表、接口信息表、接口参数表:

项目表: 记录项目信息,记录项目接口来源(Swagger接口、文档)。

接口信息表: 记录接口信息(url、请求方法、请求类型等)。

接口参数表: 记录接口参数。

获取接口信息方法

根据不同获取接口信息的类型,来获取接口信息数据。urlToJson方法是根据Swagger接口来获取接口信息:

@Override
public void createApi(ProjectDTO projectDto) throws IOException {
    switch (projectDto.getType()) {
        case 0:
            JSONObject apiJson = urlToJson(projectDto.getApi_url());
            swaggerToApi(apiJson, projectDto.getId());
            log.info("按swagger接口生成接口信息: {}", apiJson);
            break;
        case 1:
            File file = ResourceUtils.getFile(projectDto.getFile());
            String json = new String(Files.readAllBytes(Paths.get(file.getPath())));
            JSONObject fileApiJson = JSON.parseObject(json);
            swaggerToApi(fileApiJson, projectDto.getId());
            log.info("按swagger文档生成接口信息: {}", fileApiJson);
            break;
        default:
            log.warn("不支持的项目类型: {}", projectDto.getType());
    }
}

保存数据

将获取的接口信息转成定义的ApiDTODataDTO实体,并存入到数据库:

private void swaggerToApi(JSONObject jsonObject, Integer id) {
    Swagger swagger = new SwaggerParser().parse(jsonObject.toString());
    String apiHost = Optional.ofNullable(swagger.getHost()).orElse("");
    Map<String, Path> pathsMap = swagger.getPaths();
    Map<String, Model> definitionsMap = swagger.getDefinitions();
    if (pathsMap != null) {
        for (Map.Entry<String, Path> entry : pathsMap.entrySet()) {
            String path = entry.getKey();
            Path valueMap = entry.getValue();
            ApiDTO apiDto = new ApiDTO();
            apiDto.setPid(id);
            apiDto.setUrl("http://" + apiHost + path);
            Operation operation = getOperation(valueMap);
            if (operation != null) {
                String method = getHttpMethod(valueMap);
                apiDto = addApiDto(operation, method, apiDto);
                apiMapper.addApi(apiDto);
                processParameters(operation, apiDto, definitionsMap);
            }
        }
    }
}

private Operation getOperation(Path path) {
    if (path.getGet() != null) {
        return path.getGet();
    } else if (path.getPost() != null) {
        return path.getPost();
    } else if (path.getPut() != null) {
        return path.getPut();
    } else if (path.getDelete() != null) {
        return path.getDelete();
    }
    return null;
}
private String getHttpMethod(Path path) {
    if (path.getGet() != null) {
        return "GET";
    } else if (path.getPost() != null) {
        return "POST";
    } else if (path.getPut() != null) {
        return "PUT";
    } else if (path.getDelete() != null) {
        return "DELETE";
    }
    return "";
}
private void processParameters(Operation operation, ApiDTO apiDto, Map<String, Model> definitionsMap) {
    List<Parameter> parameters = operation.getParameters();
    if (parameters != null) {
        for (Parameter parameter : parameters) {
            DataDTO dataDto = new DataDTO();
            dataDto.setApi_id(apiDto.getId());
            if (parameter instanceof BodyParameter) {
                processBodyParameter((BodyParameter) parameter, dataDto, definitionsMap);
            } else if (parameter instanceof QueryParameter) {
                processQueryParameter((QueryParameter) parameter, dataDto);
            } else if (parameter instanceof FormParameter) {
                processFormParameter((FormParameter) parameter, dataDto);
            }
        }
    }
}
private void processBodyParameter(BodyParameter bodyParameter, DataDTO dataDto, Map<String, Model> definitionsMap) {
    String schema = StringUtils.substringAfterLast(Optional.ofNullable(bodyParameter.getSchema())
            .map(s -> s.getReference()).orElse(""), "/");
    Map<String, Property> map = Optional.ofNullable(bodyParameter.getSchema())
            .map(s -> s.getProperties()).orElse(new HashMap<>());
    if (schema != null && definitionsMap.containsKey(schema)) {
        ModelImpl model = (ModelImpl) definitionsMap.get(schema);
        Map<String, Property> properties = model.getProperties();
        if (properties != null) {
            for (Map.Entry<String, Property> entry : properties.entrySet()) {
                Property property = entry.getValue();
                fillDataDto(dataDto, entry.getKey(), property);
                dataMapper.addData(dataDto);
            }
        }
    } else if (!map.isEmpty()) {
        for (Map.Entry<String, Property> entry : map.entrySet()) {
            Property property = entry.getValue();
            fillDataDto(dataDto, entry.getKey(), property);
            dataMapper.addData(dataDto);
        }
    }
}
private void processQueryParameter(QueryParameter queryParameter, DataDTO dataDto) {
    dataDto.setKey(queryParameter.getName());
    dataDto.setValue(Optional.ofNullable(queryParameter.getVendorExtensions())
            .map(ext -> ext.get("x-example"))
            .map(Object::toString)
            .orElse(""));
    dataDto.setIs_required(queryParameter.getRequired() ? 0 : 1);
    dataDto.setType(mapPropertyType(queryParameter.getType(), queryParameter.getItems()));
    dataMapper.addData(dataDto);
}
private void processFormParameter(FormParameter formParameter, DataDTO dataDto) {
    dataDto.setKey(formParameter.getName());
    dataDto.setValue(Optional.ofNullable(formParameter.getVendorExtensions())
            .map(ext -> ext.get("x-example"))
            .map(Object::toString)
            .orElse(""));
    dataDto.setIs_required(formParameter.getRequired() ? 0 : 1);
    dataDto.setType(mapPropertyType(formParameter.getType(), formParameter.getItems()));
    dataMapper.addData(dataDto);
}
private void fillDataDto(DataDTO dataDto, String key, Property property) {
    dataDto.setKey(key);
    dataDto.setValue(Optional.ofNullable(property.getExample()).map(Object::toString).orElse(""));
    dataDto.setType(mapPropertyType(property.getType(), null));
    dataDto.setIs_required(property.getRequired() ? 0 : 1);
}
private String mapPropertyType(String type, Property items) {
    if (type == null) {
        return "string";
    }
    switch (type) {
        case "array":
            if (items != null) {
                switch (items.getType()) {
                    case "string":
                        return "strArray";
                    case "integer":
                        return "intArray";
                    case "object":
                        return "dictArray";
                }
            }
            return "dict";
        case "integer":
            return "int";
        case "object":
            return "dict";
        default:
            return type;
    }
}
private ApiDTO addApiDto(Operation operation, String method, ApiDTO apiDto) {
    apiDto.setName(operation.getSummary());
    apiDto.setMethod(method.toUpperCase(Locale.ROOT));
    apiDto.setData_type(determineDataType(operation, method));
    return apiDto;
}
private String determineDataType(Operation operation, String method) {
    List<String> consumes = operation.getConsumes();
    List<String> produces = operation.getProduces();
    if (!"GET".equals(method) && consumes != null && !consumes.isEmpty()) {
        return mapContentType(consumes.get(0));
    } else if (produces != null && !produces.isEmpty()) {
        return mapContentType(produces.get(0));
    }
    return "GET".equals(method) ? "params" : "";
}
private String mapContentType(String contentType) {
    if (contentType.contains("json")) {
        return "json";
    } else if (contentType.contains("params")) {
        return "params";
    } else if (contentType.contains("form-data")) {
        return "form-data";
    } else if (contentType.contains("form-urlencoded")) {
        return "form-urlencoded";
    }
    return "";
}

通过上面的方法,我们实现了自动获取接口信息,也可以根据我们项目实际情况,增加一些拓展,来定制化自己的接口信息获取方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值