前言:
用户社区 https://sonic-cloud.wiki/
官方网站 https://sonic-cloud.gitee.io/
一、 方案概述
云测平台新增脚本模式,可在平台上直接上传脚本;
云测平台新增任务模式,任务可关联脚本、设备、agent 等信息;任务支持立即执行、修改、定期执行、查看报告等基本功能;
白屏监控可作为其中的一项任务执行,关联至白屏监控脚本上;文章源自玩技e族-https://www.playezu.com/189701.html
二、 sonic 脚本管理
2.1 前端 ui 设计
导航栏新增一列脚本管理,页面展示:
操作行:新增脚本
脚本列表,列表后展示操作按钮,包括:删除、调试、下载
权限管理:初期全放开,后期接入权限模块后再做详细拆分文章源自玩技e族-https://www.playezu.com/189701.html
参考:
文章源自玩技e族-https://www.playezu.com/189701.html
2.2 新增脚本
点击按钮,可以选择文件/文件夹(或者压缩包)上传,此处可直接使用现有实现逻辑(压测平台参数化接口),将对应文件上传至 wos 存储
存储成功后,将该脚本相关信息存储至脚本表中文章源自玩技e族-https://www.playezu.com/189701.html
表设计如下:文章源自玩技e族-https://www.playezu.com/189701.html
脚本 id | 脚本名称 | 关联任务 id | 资源 url | 创建时间 | 更新人员 | 创建人员 | 更新时间 | 脚本类型 | md5 校验 | 文件大小 | 删除位标记 | 脚本状态 | 扩展字段 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | script_name | task_id | res_url | create_time | update_uid | create_uid | update_time | script_type | md5_value | res_size | flag_deleted | script_status | export |
2.2.1 前端交互设计
参考:https://blog.csdn.net/weixin_46038888/article/details/124117369文章源自玩技e族-https://www.playezu.com/189701.html
// 新增上传操作
// HTML
<el-upload
ref="upload"
class="upload-demo"
action="#"
accept=".xlsx, .xls"
:auto-upload="false"
:on-change="uploadFile"
:show-file-list="false"
>
<el-button type="warning">导入商品</el-button>
</el-upload>
// JS
uploadFile (item) {
let formData = new FormData()
let file = item.raw
formData.append('file', file)
this.$http({
url: '', //后端提供的接口
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(({data}) => {
this.$alert(data.data)
})
}
2.2.2 后端逻辑
新增接口,包装墨洁的上传接口
当文件上传成功后,
将新增上传文件相关信息落库
参考:
文章源自玩技e族-https://www.playezu.com/189701.html
创建两个脚本类型: DTO+VO
script.java文章源自玩技e族-https://www.playezu.com/189701.html
package org.cloud.sonic.common.models.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.gitee.sunchenbin.mybatis.actable.annotation.*;
import com.gitee.sunchenbin.mybatis.actable.constants.MySqlCharsetConstant;
import com.gitee.sunchenbin.mybatis.actable.constants.MySqlEngineConstant;
import org.cloud.sonic.common.models.base.TypeConverter;
import org.cloud.sonic.common.models.dto.TestSuitesDTO;
import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@ApiModel(value = "脚本对象", description = "")
@Data
@Accessors(chain = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("script")
@TableComment("脚本对象表")
@TableCharset(MySqlCharsetConstant.DEFAULT)
@TableEngine(MySqlEngineConstant.InnoDB)
public class Script implements Serializable, TypeConverter<Script, ScriptDTO> {
@TableId(value = "id", type = IdType.AUTO)
@IsAutoIncrement
private Integer id;
@TableField
@TableLogic
@Column(isNull = false, comment = "脚本状态")
private boolean deleted;
@TableField
@Column(value = "resource_url", isNull = false, comment = "脚本资源url")
private String resourceUrl;
@TableField
@Column(value = "create_time", isNull = false, comment = "创建时间")
private String createTime;
@TableField
@Column(value = "update_time", comment = "更新时间")
private String updateTime;
@TableField
@Column(value = "create_person", isNull = false, comment = "创建人员")
private String createPerson;
@TableField
@Column(value = "update_person", comment = "更新人员")
private String updatePerson;
@TableField
@Column(isNull = false, comment = "脚本类型")
private String type;
@TableField
@Column(isNull = false, comment = "脚本大小")
private Integer size;
@TableField
@Column(value = "renwu_id", isNull = false, comment = "脚本关联任务ID")
@Index(value = "IDX_PROJECT_ID", columns = {"id"})
private Integer renwuId;
}
scriptDTO.java文章源自玩技e族-https://www.playezu.com/189701.html
package org.cloud.sonic.common.models.dto;
import org.cloud.sonic.common.models.base.TypeConverter;
import org.cloud.sonic.common.models.domain.TestSuites;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Positive;
import java.io.Serializable;
import java.util.List;
@ApiModel("测试套件DTO 模型")
@Data
@Accessors(chain = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TestSuitesDTO implements Serializable, TypeConverter<TestSuitesDTO, TestSuites> {
@ApiModelProperty(value = "id", example = "1")
Integer id;
@NotBlank
@ApiModelProperty(value = "测试套件名称", required = true, example = "首页测试套件")
String name;
@Positive
@ApiModelProperty(value = "测试套件平台类型", required = true, example = "1")
Integer platform;
@Positive
@ApiModelProperty(value = "覆盖类型", required = true, example = "1")
Integer cover;
@Positive
@ApiModelProperty(value = "项目id", required = true, example = "1")
Integer projectId;
@ApiModelProperty(value = "包含的测试用例")
List<TestCasesDTO> testCases;
@ApiModelProperty(value = "指定设备列表")
List<DevicesDTO> devices;
}
添加 mappler 文件文章源自玩技e族-https://www.playezu.com/189701.html
package org.cloud.sonic.controller.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.cloud.sonic.common.models.domain.TestSuites;
import org.apache.ibatis.annotations.Mapper;
/**
* Mapper 接口
* @author JayWenStar
* @since 2021-12-17
*/
@Mapper
public interface TestSuitesMapper extends BaseMapper<TestSuites> {
}
2.3 删除脚本
将该脚本状态置为 DELETE
调用 save 接口
2.4 下载脚本
将该文件资源下载至本地,新增一个下载接口
2.5 脚本调试执行(初步方案,后期优化前端加上执行日志展示框)
2.5.1 整体流程
- 发起调试执行接口
- 接口调用脚本调试方法
- server 端处理一些异常判断,分配执行 agent 与设备,从数据库获取该脚本相关信息,拼接消息类型下发至 agent
- agent 端:脚本下载、判断任务类型、环境校验/配置、调用脚本执行
- agent 端:等待 Python 脚本回调消息,Python 脚本执行完毕后,给 java 一个回调
- agent 端:整体任务执行完毕后,给 server 通信
2.5.2 server 处理流程
2.5.3 agent 处理流程
三、任务管理
实现逻辑
可直接参考 org.cloud.sonic.simple.controller.TestSuitesController.runSuite 方法
public RespModel<String> runSuite(int suiteId, String strike) {
TestSuitesDTO testSuitesDTO;
if (existsById(suiteId)) {
testSuitesDTO = findById(suiteId);
} else {
return new RespModel<>(3001, "测试套件已删除!");
}
if (testSuitesDTO.getTestCases().size() == 0) {
return new RespModel<>(3002, "该测试套件内无测试用例!");
}
List<Devices> devicesList = BeanTool.transformFromInBatch(testSuitesDTO.getDevices(), Devices.class);
for (int i = devicesList.size() - 1; i >= 0; i--) {
if (devicesList.get(i).getStatus().equals(DeviceStatus.OFFLINE) || devicesList.get(i).getStatus().equals(DeviceStatus.DISCONNECTED)) {
devicesList.remove(devicesList.get(i));
}
}
if (devicesList.size() == 0) {
return new RespModel<>(3003, "所选设备暂无可用!");
}
四、整体设计方案流程
##4.1 server 执行任务流程
##4.2 agent 执行任务流程
4.3 脚本执行流程
软件测试支付功能怎么测试