【测试开发】十二、接口测试-实现接口列表功能-递归查询子节点下的接口

简介: 【测试开发】十二、接口测试-实现接口列表功能-递归查询子节点下的接口

基于 springboot+vue 的测试平台开发继续更新。


模块树节点的开发暂告一段落,现在开发右边接口相关的部分,今天先完成列表的功能。


功能是这样,当点击树的某个节点时候,右侧列表展示这个节点下的所有接口,带分页(最终效果图)。


1268169-20211016104153244-239118782.png


需要注意的是,因为节点下还有子节点,所以列表的功能需要使用递归来查询。


一、后端


1. 建表


想了一些字段,可能后续还会有些改动,暂时先这样:


CREATE TABLE `api_definition` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `projectId` bigint NOT NULL COMMENT '所属项目id',
  `name` varchar(255) NOT NULL COMMENT '接口名称',
  `method` varchar(64) NOT NULL COMMENT '请求方法',
  `path` varchar(1000) DEFAULT NULL COMMENT '接口路径',
  `description` longtext COMMENT '接口描述',
  `apiHeader` varchar(255) DEFAULT NULL COMMENT '请求头',
  `request` longtext COMMENT '请求内容 (JSON format)',
  `response` longtext COMMENT '响应内容 (JSON format)',
  `createTime` datetime DEFAULT '1900-01-01 00:00:00' COMMENT '创建时间',
  `updateTime` datetime DEFAULT '1900-01-01 00:00:00' COMMENT '更新时间',
  `createUser` varchar(30) DEFAULT NULL COMMENT '创建人',
  `moduleId` bigint NOT NULL COMMENT '所属模块id',
  `host` varchar(255) DEFAULT NULL COMMENT '接口域名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='接口定义表';


2. 列表接口


(1)实体类 ApiDefinition


@Data
@TableName("api_definition")
public class ApiDefinition {
    @TableId(type = IdType.AUTO)
    private Long id;
    private Long projectId;
    private String name;
    private String method;
    private String path;
    private String host;
    private String description;
    private String apiHeader;
    private String request;
    private String response;
    private Long moduleId;
    private String createUser;
    @TableField(fill = FieldFill.INSERT)        // 新增的时候填充数据
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE) // 新增或修改的时候填充数据
    private Date updateTime;
}


(2)DAO层


@Repository
public interface ApiDefinitionDAO extends BaseMapper<ApiDefinition> {
}


(3)Controller 层


@RestController
@RequestMapping("apiDefinition")
public class ApiDefinitionController {
    @Autowired
    ApiDefinitionService apiDefinitionService;
    @GetMapping("/list/{projectId}/{moduleId}/{currentPage}/{pageSize}")
    public Result list(@PathVariable Long projectId,
                       @PathVariable Long moduleId,
                       @PathVariable int currentPage,
                       @PathVariable int pageSize) {
        IPage<ApiDefinition> IPageProject = apiDefinitionService.list(projectId, moduleId, currentPage, pageSize);
        return Result.success(IPageProject);
    }
}


这里路径有 4 个参数,moduleId 用来查询模块下的所有接口(包含本节点+子节点),后面2个则是分页查询参数。


(4)Service 层


在 service 层实现 list 方法,用来查询接口。


@Service
public class ApiDefinitionService {
    @Autowired
    ApiDefinitionDAO apiDefinitionDAO;
    @Autowired
    ApiModuleDAO apiModuleDAO;
    public IPage<ApiDefinition> list(Long projectId, Long moduleId, int currentPage, int pageSize) {
        // 查询项目id下所有模块
        QueryWrapper<ApiModule> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("projectId", projectId);
        List<ApiModule> apiModules = apiModuleDAO.selectList(queryWrapper);
        // 调用递归查询,childrenIds存放查询到的模块 id
        List<Long> childrenIds = new ArrayList<>();
        List<Long> ids = moduleRecursion(childrenIds, apiModules, moduleId);
        // 添加上入参的模块id
        ids.add(moduleId);
        // 查询模块id下的api
        Page<ApiDefinition> pageApiDefinition = new Page<>(currentPage, pageSize);
        QueryWrapper<ApiDefinition> queryApiWrapper = new QueryWrapper<>();
        queryApiWrapper.in("moduleId", ids)
                       .orderByDesc("id");
        return apiDefinitionDAO.selectPage(pageApiDefinition, queryApiWrapper);
    }
    private List<Long> moduleRecursion(List<Long> children, List<ApiModule> modules, Long pid) {
        for (ApiModule apiModule : modules) {
            //遍历出父id等于pid,add进子节点集合
            if (apiModule.getParentId().equals(pid)) {
                // 递归遍历下一级
                moduleRecursion(children, modules, apiModule.getId());
                children.add(apiModule.getId());
            }
        }
        return children;
    }
}


list方法中调用递归查询方法moduleRecursion,有3个参数:


  • List<Long> children:用来存放子节点的 id,最后返回出来
  • List<ApiModule> modules:项目id下的模块
  • Long pid:就是当前要查询的模块id


for 循环遍历项目下的所有模块id,每一层里判断apiModule.getParentId().equals(pid),相等的话继续递归遍历,最后把结果返回。


list方法拿到之后,还有一步别忘记了,就是入参的这个模块本身,也需要加进去ids.add(moduleId),最后进行分页查询。


在表里加点测试数据,然后测试下查询接口没问题。


二、前端


1. 准备工作


新建apiDefinition.js文件,存放接口。


import request from '@/utils/request'
export function getApiListByModuleId(projectId, moduleId, current, size) {
  return request({
    url: `/bloomtest/apiDefinition/list/${projectId}/${moduleId}/${current}/${size}`,
    method: 'get'
  })
}


接着,去掉之前写死的假数据,变成空数组,从后端接口拿到的数组就放到这。


1268169-20211010200822449-1961234141.png


2. 请求接口


组件里有个事件node-click,节点被点击时的回调。


1268169-20211010201034777-1060100851.png


这里绑定了一个方法getApi,在这个方法里会进行接口请求的操作,来实现这个方法:


1268169-20211016111426774-1563418425.png


传入 data 是可以获得节点 id 的,可以直接用。


注意,这里还是需要用到一个中间字段currentNode,本来没有用直接使用 data,后来发现点击分页的时候有bug。


1268169-20211016111541832-1311996809.png


这是因为 data 是点击左侧树节点的时候才有,所以还是先存起来。


1268169-20211016111552079-1679885599.png


列表中的这些prop的值注意跟接口返回的字段对应。


1268169-20211010201236396-56430160.png


分页的地方,注意下调用的方法即可。


1268169-20211016111849449-1037222572.png


3. 测试效果


在表里新建了个数据,点击这个接口关联的模块,列表可以呈现数据。


1268169-20211016112243212-1874091848.gif


4. 发现问题


问题1


功能实现了,但是发现了个问题。


就是当我点击节点上的 添加、编辑等按钮的时候,也会触发这个事件,调用了接口列表的方法。


但是看在不影响各自功能的使用,先不去管它。


问题2


刚才我测试是在项目3下进行的,是可以查出来一条数据。但是当我切换项目到还没数据的项目2下,页面没有刷新,还是呈现的刚才的数据。


1268169-20211010202415183-1898051192.png


修改方法就是当切换项目的时候,查询出这个项目下的所有接口数据。


找到下来框的元素,之前已经绑定过一个方法queryModuleList,然后现在再加一个方法,用来查询项目下的接口。


1268169-20211016114114941-100066541.png


@change="queryModuleList();initProjectApi()",方法加上括号,2个方法用;隔开。


实现这个新的方法initProjectApi


1268169-20211016114334680-1279072461.png


依然是调用列表接口,这里的模块id可以直接传 0,因为所有项目下的模块,顶级的节点id都是 0 。


1268169-20211016114633448-1724396158.gif


测试功能正常。

相关文章
|
1月前
|
运维
【运维基础知识】用dos批处理批量替换文件中的某个字符串(本地单元测试通过,部分功能有待优化,欢迎指正)
该脚本用于将C盘test目录下所有以t开头的txt文件中的字符串“123”批量替换为“abc”。通过创建批处理文件并运行,可实现自动化文本替换,适合初学者学习批处理脚本的基础操作与逻辑控制。
134 56
|
6天前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
34 3
|
1月前
|
JSON 算法 数据可视化
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
这篇文章是关于如何通过算法接口返回的目标检测结果来计算性能指标的笔记。它涵盖了任务描述、指标分析(包括TP、FP、FN、TN、精准率和召回率),接口处理,数据集处理,以及如何使用实用工具进行文件操作和数据可视化。文章还提供了一些Python代码示例,用于处理图像文件、转换数据格式以及计算目标检测的性能指标。
57 0
测试专项笔记(一): 通过算法能力接口返回的检测结果完成相关指标的计算(目标检测)
|
1月前
|
测试技术
Appscan手工探索、手工测试功能实战
Appscan手工探索、手工测试功能实战
|
2月前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
237 7
Jmeter实现WebSocket协议的接口测试方法
|
2月前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
247 3
快速上手|HTTP 接口功能自动化测试
|
1月前
|
JavaScript 前端开发 API
vue尚品汇商城项目-day02【9.Home组件拆分+10.postman测试接口】
vue尚品汇商城项目-day02【9.Home组件拆分+10.postman测试接口】
40 0
|
2月前
|
JavaScript 前端开发 测试技术
ChatGPT与接口测试
ChatGPT与接口测试,测试通过
48 5
|
3月前
|
网络协议 测试技术 网络安全
Python进行Socket接口测试的实现
在现代软件开发中,网络通信是不可或缺的一部分。无论是传输数据、获取信息还是实现实时通讯,都离不开可靠的网络连接和有效的数据交换机制。而在网络编程的基础中,Socket(套接字)技术扮演了重要角色。 Socket 允许计算机上的程序通过网络进行通信,它是网络通信的基础。Python 提供了强大且易于使用的 socket 模块,使开发者能够轻松地创建客户端和服务器应用,实现数据传输和交互。 本文将深入探讨如何利用 Python 编程语言来进行 Socket 接口测试。我们将从基础概念开始介绍,逐步引导大家掌握创建、测试和优化 socket 接口的关键技能。希望本文可以给大家的工作带来一些帮助~
|
4月前
|
存储
Postman 接口测试配置 Pre-request Script
Postman 接口测试配置 Pre-request Script
210 5
Postman 接口测试配置 Pre-request Script