Commit 57f0575a authored by 黎博's avatar 黎博

接口自动化重新设计

parent 455049d8
package cn.qg.holmes.controller.auto;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.service.auto.AutoModuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 接口自动化模块controller
* @author libo
*/
@CrossOrigin
@RestController
@RequestMapping("/auto/module")
public class AutoModuleController {
@Autowired
AutoModuleService autoModuleService;
@GetMapping("/list")
public JsonResult getAutoModuleList(Integer pageNum, Integer pageSize) {
return null;
}
}
package cn.qg.holmes.controller.auto;
public class InterfaceController {
}
package cn.qg.holmes.controller.auto;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.auto.Project;
import cn.qg.holmes.service.auto.ProjectService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* 接口自动化项目相关controller
* @author libo
*/
@CrossOrigin
@RestController
@RequestMapping("/auto/project")
public class ProjectController {
@Autowired
ProjectService projectService;
/**
* 获取项目列表
* @param pageNum 第几页
* @param pageSize 每页数量
* @return
*/
@GetMapping("/list")
public JsonResult getAutoProjectList(@RequestParam Integer pageNum, @RequestParam Integer pageSize) {
IPage<Project> projectIPage = new Page<>(pageNum, pageSize);
IPage<Project> projectPageEntity = projectService.page(projectIPage);
Map<String, Object> map = new HashMap<>();
map.put("list", projectPageEntity.getRecords());
map.put("total", projectPageEntity.getTotal());
return JsonResult.buildSuccessResult(map);
}
/**
* 新增项目
* @param project 项目实体
* @return
*/
@PostMapping("/add")
public JsonResult autoProjectAdd(@RequestBody Project project) {
// 判断项目是否已存在
QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", project.getName());
if (projectService.getOne(queryWrapper) != null) {
return JsonResult.buildErrorStateResult("该名称项目已存在!", false);
} else {
return JsonResult.buildSuccessResult(projectService.save(project));
}
}
/**
* 修改项目
* @param project 项目实体
* @return
*/
@PostMapping("/modify")
public JsonResult autoProjectModify(@RequestBody Project project) {
if (projectService.getById(project.getId()) == null) {
return JsonResult.buildErrorStateResult("项目不存在", false);
} else {
return JsonResult.buildSuccessResult(projectService.updateById(project));
}
}
/**
* 删除项目
* @param projectId 项目id
*/
@GetMapping("/delete")
public JsonResult autoProjectDelete(@RequestParam Integer projectId) {
if (projectService.getById(projectId) == null) {
return JsonResult.buildErrorStateResult("该项目不存在!", false);
} else {
return JsonResult.buildSuccessResult(projectService.removeById(projectId));
}
}
}
package cn.qg.holmes.controller.auto;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.entity.auto.AutoModule;
import cn.qg.holmes.entity.auto.Scene;
import cn.qg.holmes.entity.auto.Testcase;
import cn.qg.holmes.service.auto.AutoModuleService;
import cn.qg.holmes.service.auto.SceneService;
import cn.qg.holmes.service.auto.SceneTestcaseService;
import cn.qg.holmes.service.auto.TestcaseService;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
/**
* 测试用例执行controller
* @author libo
*/
@CrossOrigin
@RestController
@RequestMapping("/execute")
@RequestMapping("/auto/execute")
public class TestExecutionController {
@Autowired
......@@ -16,13 +32,56 @@ public class TestExecutionController {
@Autowired
SceneTestcaseService sceneTestcaseService;
@Autowired
SceneService sceneService;
@Autowired
AutoModuleService autoModuleService;
/**
* 执行单个用例
* @param namespace 环境
* @param testcaseId 用例id
* @return
*/
@GetMapping("/testcase")
public void testSingleTestcase(@RequestParam Integer testcaseId) {
testcaseService.singleTestcaseExecutor(testcaseId);
public JsonResult executeSingleTestcase(@RequestParam String namespace, @RequestParam Integer testcaseId) {
Testcase testcase = testcaseService.getById(testcaseId);
String testcaseName = testcase.getName();
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SS");
String batch = dateFormat.format(date) + "_" + testcaseName;
return JsonResult.buildSuccessResult(JSON.parseObject(testcaseService.singleTestcaseExecutor(namespace, testcaseId, batch), Map.class));
}
/**
* 执行一个模块下所有用例
* @param namespace 环境
* @param moduleId 模块id
* @return
*/
@GetMapping("/module")
public JsonResult executeTestcaseByModule(@RequestParam String namespace, @RequestParam Integer moduleId) {
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SS");
AutoModule autoModule = autoModuleService.getById(moduleId);
String moduleName = autoModule.getName();
String batch = dateFormat.format(date) + "_" + moduleName;
return JsonResult.buildSuccessResult(JSON.parseArray(testcaseService.executeTestcaseByModuleId(namespace, moduleId, batch)));
}
/**
* 执行场景用例
* @param namespace 环境
* @param sceneId 场景id
* @return
*/
@GetMapping("/scene")
public void testScene(@RequestParam Integer sceneId) {
sceneTestcaseService.executeSceneTestcase(sceneId);
public JsonResult executeSceneTestcase(String namespace, Integer sceneId) {
Date date = new Date();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SS");
Scene scene = sceneService.getById(sceneId);
String batch = dateFormat.format(date) + "_" + scene.getName();
return JsonResult.buildSuccessResult(JSON.parseArray(sceneTestcaseService.executeSceneTestcase(namespace, sceneId, batch)));
}
}
package cn.qg.holmes.controller.auto;
import cn.qg.holmes.common.JsonResult;
import cn.qg.holmes.service.auto.SceneTestcaseReportService;
import cn.qg.holmes.service.auto.TestcaseReportService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 报告相关接口
*
* @author libo
*/
@CrossOrigin
@RestController
@RequestMapping("/report")
public class TestReportController {
@Autowired
TestcaseReportService testcaseReportService;
@Autowired
SceneTestcaseReportService sceneTestcaseReportService;
@GetMapping("/testcase/batch")
public JsonResult getTestcaseReportByBatch(String batch) {
return null;
}
@GetMapping("/scene/batch")
public JsonResult getSceneReportByBatch() {
return null;
}
@GetMapping("/testcase/list")
public JsonResult getTestcaseReportListByNamespace(String namespace,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
return JsonResult.buildSuccessResult(testcaseReportService.getTestcaseReportByNamespace(namespace, pageNum, pageSize));
}
@GetMapping("/scene/list")
public JsonResult getSceneTestcaseReportListByNamespace(String namespace,
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
return JsonResult.buildSuccessResult(sceneTestcaseReportService.getSceneTestcaseReportListByNamespace(namespace, pageNum, pageSize));
}
}
package cn.qg.holmes.controller.auto;
public class TestcaseController {
}
......@@ -15,6 +15,10 @@ import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
/**
* Mock相关controller
* @author libo
*/
@Slf4j
@CrossOrigin
@RestController
......
package cn.qg.holmes.entity.auto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* 接口自动化-模块实体类
* @author libo
*/
@TableName(value = "auto_module")
@Data
public class AutoModule {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String description;
private String domain;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
......@@ -9,6 +9,7 @@ import java.util.Date;
/**
* 接口实体类
* @author libo
*/
@Data
public class Interface {
......@@ -22,7 +23,7 @@ public class Interface {
private String requestTemplate;
private String responseTemplate;
private String author;
private Integer projectId;
private Integer moduleId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
......
package cn.qg.holmes.entity.auto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
......@@ -9,14 +10,14 @@ import java.util.Date;
/**
* 项目实体类
* @author libo
*/
@Data
public class Project {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String key;
private String domain;
private String description;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
......
......@@ -10,6 +10,7 @@ import java.util.Date;
/**
* 场景实体类
* @author libo
*/
@Data
@TableName("scene")
......
......@@ -8,6 +8,10 @@ import lombok.Data;
import java.util.Date;
/**
* 场景用例实体类
* @author libo
*/
@Data
@TableName("scene_testcase")
public class SceneTestcase {
......
package cn.qg.holmes.entity.auto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* 场景用例报告
* @author libo
*/
@TableName(value = "scene_testcase_report")
@Data
public class SceneTestcaseReport {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer sceneId;
private Integer sceneTestcaseId;
private String url;
private String headers;
private String parameters;
private String response;
private String validate;
private String status;
private Long elapsedTime;
private Integer sequence;
private String batch;
private Integer projectId;
private String namespace;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
......@@ -10,6 +10,7 @@ import java.util.Date;
/**
* 单接口用例实体类
* @author libo
*/
@TableName("testcase")
@Data
......@@ -25,6 +26,7 @@ public class Testcase {
private String variables;
private String extract;
private String validate;
private Integer moduleId;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
......
package cn.qg.holmes.entity.auto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
/**
* 测试报告实体类
* @author libo
*/
@TableName(value = "testcase_report")
@Data
public class TestcaseReport {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer testcaseId;
private String headers;
private String parameters;
private String response;
private String validate;
private String status;
private Long elapsedTime;
private String batch;
private Integer moduleId;
private String namespace;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
package cn.qg.holmes.mapper.auto;
import cn.qg.holmes.entity.auto.AutoModule;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface AutoModuleMapper extends BaseMapper<AutoModule> {
}
package cn.qg.holmes.mapper.auto;
import cn.qg.holmes.entity.auto.SceneTestcaseReport;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface SceneTestcaseReportMapper extends BaseMapper<SceneTestcaseReport> {
}
package cn.qg.holmes.mapper.auto;
import cn.qg.holmes.entity.auto.TestcaseReport;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface TestcaseReportMapper extends BaseMapper<TestcaseReport> {
}
package cn.qg.holmes.service.auto;
import cn.qg.holmes.entity.auto.AutoModule;
import com.baomidou.mybatisplus.extension.service.IService;
public interface AutoModuleService extends IService<AutoModule> {
}
......@@ -2,14 +2,15 @@ package cn.qg.holmes.service.auto;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public interface AutoUtilsService {
Map<String, String> replaceHeaders(String headers, String variables);
Map<String, String> replaceHeaders(String headers, String variables, UUID uuid);
Map<String, String> replaceParameters(String parameters, String variables);
Map<String, String> replaceParameters(String parameters, String variables, UUID uuid);
boolean extractResponse(String response, String extract);
boolean extractResponse(String response, String extract, UUID uuid);
boolean assertResponse(String response, List<Map> validateList);
}
......@@ -4,4 +4,5 @@ import cn.qg.holmes.entity.auto.Project;
import com.baomidou.mybatisplus.extension.service.IService;
public interface ProjectService extends IService<Project> {
}
package cn.qg.holmes.service.auto;
import cn.qg.holmes.entity.auto.SceneTestcaseReport;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.Map;
public interface SceneTestcaseReportService extends IService<SceneTestcaseReport> {
Map<String, Object> getSceneTestcaseReportListByNamespace(String namespace, Integer pageNum, Integer pageSize);
}
......@@ -5,5 +5,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
public interface SceneTestcaseService extends IService<SceneTestcase> {
void executeSceneTestcase(Integer sceneId);
String executeSceneTestcase(String namespace, Integer sceneId, String batch);
}
package cn.qg.holmes.service.auto;
import cn.qg.holmes.entity.auto.TestcaseReport;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.Map;
public interface TestcaseReportService extends IService<TestcaseReport> {
Map<String, Object> getTestcaseReportByNamespace(String namespace, Integer pageNum, Integer pageSize);
}
......@@ -5,5 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
public interface TestcaseService extends IService<Testcase> {
String singleTestcaseExecutor(Integer testcaseId);
String singleTestcaseExecutor(String namespace, Integer testcaseId, String batch);
String executeTestcaseByModuleId(String namespace, Integer moduleId, String batch);
}
package cn.qg.holmes.service.auto.impl;
import cn.qg.holmes.entity.auto.AutoModule;
import cn.qg.holmes.mapper.auto.AutoModuleMapper;
import cn.qg.holmes.service.auto.AutoModuleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class AutoModuleServiceImpl extends ServiceImpl<AutoModuleMapper, AutoModule> implements AutoModuleService {
}
......@@ -10,6 +10,7 @@ import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* @author libo
......@@ -28,7 +29,7 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
* @param variables 参数json
* @return
*/
public Map<String, String> replaceHeaders(String headers, String variables) {
public Map<String, String> replaceHeaders(String headers, String variables, UUID uuid) {
log.info("开始执行请求头替换!");
Map<String, String> headersMap = JSON.parseObject(headers, Map.class);
Map<String, String> varMap = JSON.parseObject(variables, Map.class);
......@@ -36,7 +37,7 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
log.info("参数列表:{}", varMap);
for (String key: varMap.keySet()) {
String value = varMap.get(key);
headersMap.put(key, redisUtils.get(value.substring(1)).toString());
headersMap.put(key, redisUtils.get(uuid + "_" + value.substring(1)).toString());
}
log.info("替换之后的headers:{}", headersMap);
return headersMap;
......@@ -48,7 +49,7 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
* @param variables 变量json
* @return 替换后的参数Map
*/
public Map<String, String> replaceParameters(String parameters, String variables) {
public Map<String, String> replaceParameters(String parameters, String variables, UUID uuid) {
log.info("开始执行请求参数替换!");
Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class);
Map<String, String> varMap = JSON.parseObject(variables, Map.class);
......@@ -56,7 +57,7 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
log.info("参数列表:{}", varMap);
for (String key: varMap.keySet()) {
String value = varMap.get(key);
parameterMap.put(key, redisUtils.get(value.substring(1)).toString());
parameterMap.put(key, redisUtils.get(uuid + "_" + value.substring(1)).toString());
}
log.info("替换之后的参数:{}", parameterMap);
return parameterMap;
......@@ -68,13 +69,14 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
* @param extract 解析的字段及保存到redis的key
* @return true-解析成功,false-解析失败
*/
public boolean extractResponse(String response, String extract) {
public boolean extractResponse(String response, String extract, UUID uuid) {
Map<String, String> extractMap = JSON.parseObject(extract, Map.class);
try {
for (String key: extractMap.keySet()) {
String value = extractMap.get(key);
redisUtils.set(key, JsonPath.read(response, value));
redisUtils.expire(key, 120);
String redisKey = uuid + "_" + key;
redisUtils.set(redisKey, JsonPath.read(response, value));
redisUtils.expire(redisKey, 120);
}
} catch (Exception e) {
e.printStackTrace();
......@@ -90,14 +92,14 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
public boolean assertResponse(String response, List<Map> validateList) {
for (Map<String, String> map: validateList) {
String comparator = map.get("comparator");
String checkpoint = JsonPath.read(response, map.get("check"));
String checkpoint = JsonPath.read(response, map.get("check")).toString();
String expectValue = map.get("expect");
boolean result = singleAssertResponse(response, comparator, checkpoint, expectValue);
if (!result) {
return false;
}
}
return false;
return true;
}
/**
......@@ -111,13 +113,13 @@ public class AutoUtilsServiceImpl implements AutoUtilsService {
public boolean singleAssertResponse(String response, String comparator, String checkpoint, String expectValue) {
switch (comparator) {
case "eq":
return JsonPath.read(response, checkpoint).equals(expectValue);
return checkpoint.equals(expectValue);
case "gt":
return Integer.parseInt(JsonPath.read(response, checkpoint)) > Integer.parseInt(expectValue);
return Integer.parseInt(checkpoint) > Integer.parseInt(expectValue);
case "lt":
return Integer.parseInt(JsonPath.read(response, checkpoint)) < Integer.parseInt(expectValue);
return Integer.parseInt(checkpoint) < Integer.parseInt(expectValue);
case "neq":
return !JsonPath.read(response, checkpoint).equals(expectValue);
return !checkpoint.equals(expectValue);
default:
log.info("暂不支持该比较符号:{}", comparator);
break;
......
......@@ -8,4 +8,5 @@ import org.springframework.stereotype.Service;
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements ProjectService {
}
package cn.qg.holmes.service.auto.impl;
import cn.qg.holmes.entity.auto.SceneTestcaseReport;
import cn.qg.holmes.mapper.auto.SceneTestcaseReportMapper;
import cn.qg.holmes.service.auto.SceneTestcaseReportService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class SceneTestcaseReportServiceImpl extends ServiceImpl<SceneTestcaseReportMapper, SceneTestcaseReport> implements SceneTestcaseReportService {
@Autowired
SceneTestcaseReportMapper sceneTestcaseReportMapper;
@Override
public Map<String, Object> getSceneTestcaseReportListByNamespace(String namespace, Integer pageNum, Integer pageSize) {
QueryWrapper<SceneTestcaseReport> queryWrapper = new QueryWrapper<>();
if (namespace != null && !namespace.isEmpty()) {
queryWrapper.eq("namespace", namespace);
}
queryWrapper.orderByDesc("id");
Page<SceneTestcaseReport> page = new Page<>(pageNum, pageSize);
IPage<SceneTestcaseReport> iPage = sceneTestcaseReportMapper.selectPage(page, queryWrapper);
Map<String, Object> map = new HashMap<>();
map.put("total", iPage.getTotal());
map.put("list", iPage.getRecords());
return map;
}
}
package cn.qg.holmes.service.auto.impl;
import cn.qg.holmes.entity.auto.AutoModule;
import cn.qg.holmes.entity.auto.Interface;
import cn.qg.holmes.entity.auto.SceneTestcase;
import cn.qg.holmes.entity.auto.SceneTestcaseReport;
import cn.qg.holmes.mapper.auto.SceneTestcaseMapper;
import cn.qg.holmes.service.auto.AutoUtilsService;
import cn.qg.holmes.service.auto.InterfaceService;
import cn.qg.holmes.service.auto.SceneTestcaseService;
import cn.qg.holmes.service.auto.TestcaseService;
import cn.qg.holmes.service.auto.*;
import cn.qg.holmes.utils.HttpClientUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
......@@ -15,9 +14,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author libo
......@@ -36,30 +33,45 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
@Autowired
InterfaceService interfaceService;
@Autowired
AutoModuleService autoModuleService;
@Autowired
AutoUtilsService autoUtilsService;
@Autowired
SceneTestcaseReportService sceneTestcaseReportService;
@Autowired
SceneService sceneService;
@Override
public void executeSceneTestcase(Integer sceneId) {
public String executeSceneTestcase(String namespace, Integer sceneId, String batch) {
UUID uuid = UUID.randomUUID();
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("scene_id", sceneId);
queryWrapper.orderByAsc("sequence");
List<SceneTestcase> sceneTestcaseList = sceneTestcaseMapper.selectList(queryWrapper);
List<Map<String, Object>> resultList = new ArrayList<>();
for (SceneTestcase sceneTestcase: sceneTestcaseList) {
sceneTestcaseExecution(sceneId, sceneTestcase.getInterfaceId());
resultList.add(JSON.parseObject(sceneTestcaseExecution(namespace, sceneId, sceneTestcase.getInterfaceId(), uuid, batch), Map.class));
}
return JSON.toJSONString(resultList);
}
public String sceneTestcaseExecution(Integer sceneId, Integer interfaceId) {
public String sceneTestcaseExecution(String namespace, Integer sceneId, Integer interfaceId, UUID uuid, String batch) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("scene_id", sceneId);
queryWrapper.eq("interface_id", interfaceId);
SceneTestcase sceneTestcase = sceneTestcaseMapper.selectOne(queryWrapper);
Interface anInterface = interfaceService.getById(interfaceId);
String url = anInterface.getUrl();
AutoModule autoModule = autoModuleService.getById(anInterface.getModuleId());
String domain = autoModule.getDomain();
String url = domain.replace("${NAMESPACE}", namespace) + anInterface.getUrl();
log.info("开始执行接口:{}", url);
String method = anInterface.getMethod().toUpperCase();
String paramType = anInterface.getParamType();
String interfaceName = anInterface.getName();
String headers = sceneTestcase.getHeaders();
String parameters = sceneTestcase.getParameters();
String variables = sceneTestcase.getVariables();
......@@ -67,17 +79,21 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
String validate = sceneTestcase.getValidate();
Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class);
Map<String, String> headersMap = JSON.parseObject(headers, Map.class);
if (variables != null && !variables.isEmpty() && parameters != null && !parameters.isEmpty()) {
parameterMap = autoUtilsService.replaceParameters(parameters, variables);
}
// 使用变量替换headers
if (variables != null && !variables.isEmpty() && headers != null && !headers.isEmpty()) {
headersMap = autoUtilsService.replaceParameters(headers, variables);
headersMap = autoUtilsService.replaceHeaders(headers, variables, uuid);
}
// 使用变量替换参数
if (variables != null && !variables.isEmpty() && parameters != null && !parameters.isEmpty()) {
parameterMap = autoUtilsService.replaceParameters(parameters, variables, uuid);
}
// 创建断言列表
List<Map> validateList = new ArrayList<>();
if (validate != null && !validate.isEmpty()) {
validateList = JSON.parseArray(validate, Map.class);
}
String response = "";
Long startTime = System.currentTimeMillis();
switch (method) {
case "GET":
response = HttpClientUtils.doGet(url, headersMap, parameterMap);
......@@ -93,15 +109,50 @@ public class SceneTestcaseServiceImpl extends ServiceImpl<SceneTestcaseMapper, S
log.info("暂不支持该请求方法:{}", method);
break;
}
Long endTime = System.currentTimeMillis();
Long elapsedTime = endTime - startTime;
log.info("本次接口的响应为:{}", response);
log.info("本次接口执行时间:{}", elapsedTime);
// 进行断言
boolean assertResult = true;
if (!validateList.isEmpty()) {
autoUtilsService.assertResponse(response, validateList);
assertResult = autoUtilsService.assertResponse(response, validateList);
}
// 解析响应
if (extract != null && !extract.isEmpty()) {
autoUtilsService.extractResponse(response, extract);
autoUtilsService.extractResponse(response, extract, uuid);
}
Map<String, Object> map = new HashMap<>();
map.put("url", url);
map.put("name", interfaceName);
map.put("headers", headersMap);
map.put("parameters", parameterMap);
map.put("assertResult", assertResult);
map.put("response", JSON.parseObject(response, Map.class));
map.put("elapsedTime", elapsedTime);
// 插入测试报告
SceneTestcaseReport sceneTestcaseReport = new SceneTestcaseReport();
sceneTestcaseReport.setSceneId(sceneId);
sceneTestcaseReport.setSceneTestcaseId(sceneTestcase.getId());
sceneTestcaseReport.setSequence(sceneTestcase.getSequence());
sceneTestcaseReport.setUrl(url);
sceneTestcaseReport.setHeaders(JSON.toJSONString(headersMap));
sceneTestcaseReport.setParameters(JSON.toJSONString(parameterMap));
if (assertResult) {
sceneTestcaseReport.setStatus("pass");
} else {
sceneTestcaseReport.setStatus("fail");
}
return response;
sceneTestcaseReport.setElapsedTime(elapsedTime);
sceneTestcaseReport.setResponse(response);
sceneTestcaseReport.setValidate(validate);
sceneTestcaseReport.setBatch(batch);
sceneTestcaseReport.setProjectId(sceneService.getById(sceneId).getProjectId());
sceneTestcaseReport.setNamespace(namespace);
log.info("保存测试报告:{}", sceneTestcaseReport);
sceneTestcaseReportService.save(sceneTestcaseReport);
return JSON.toJSONString(map);
}
}
package cn.qg.holmes.service.auto.impl;
import cn.qg.holmes.entity.auto.TestcaseReport;
import cn.qg.holmes.mapper.auto.TestcaseReportMapper;
import cn.qg.holmes.service.auto.TestcaseReportService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.Map;
@Service
public class TestcaseReportServiceImpl extends ServiceImpl<TestcaseReportMapper, TestcaseReport> implements TestcaseReportService {
@Autowired
TestcaseReportMapper testcaseReportMapper;
@Override
public Map<String, Object> getTestcaseReportByNamespace(String namespace, Integer pageNum, Integer pageSize) {
QueryWrapper<TestcaseReport> queryWrapper = new QueryWrapper<>();
if (namespace != null && !namespace.isEmpty()) {
queryWrapper.eq("namespace", namespace);
}
queryWrapper.orderByDesc("id");
Page<TestcaseReport> page = new Page<>(pageNum, pageSize);
IPage<TestcaseReport> iPage = testcaseReportMapper.selectPage(page, queryWrapper);
Map<String, Object> map = new HashMap<>();
map.put("total", iPage.getTotal());
map.put("list", iPage.getRecords());
return map;
}
}
package cn.qg.holmes.service.auto.impl;
import cn.qg.holmes.entity.auto.AutoModule;
import cn.qg.holmes.entity.auto.Interface;
import cn.qg.holmes.entity.auto.Testcase;
import cn.qg.holmes.entity.auto.TestcaseReport;
import cn.qg.holmes.mapper.auto.TestcaseMapper;
import cn.qg.holmes.service.auto.AutoUtilsService;
import cn.qg.holmes.service.auto.InterfaceService;
import cn.qg.holmes.service.auto.TestcaseService;
import cn.qg.holmes.service.auto.*;
import cn.qg.holmes.utils.HttpClientUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -31,14 +33,28 @@ public class TestcaseServiceImpl extends ServiceImpl<TestcaseMapper, Testcase> i
@Autowired
InterfaceService interfaceService;
@Autowired
AutoModuleService autoModuleService;
@Autowired
AutoUtilsService autoUtilsService;
@Autowired
TestcaseReportService testcaseReportService;
/**
* 执行单接口用例
* @param namespace 环境
* @param testcaseId 用例id
* @return
*/
@Override
public String singleTestcaseExecutor(Integer testcaseId) {
public String singleTestcaseExecutor(String namespace, Integer testcaseId, String batch) {
Testcase testcase = testcaseMapper.selectById(testcaseId);
Interface anInterface = interfaceService.getById(testcase.getInterfaceId());
String url = anInterface.getUrl();
AutoModule autoModule = autoModuleService.getById(anInterface.getModuleId());
String domain = autoModule.getDomain();
String url = domain.replace("${NAMESPACE}", namespace) + anInterface.getUrl();
String method = anInterface.getMethod().toUpperCase();
String paramType = anInterface.getParamType();
String headers = testcase.getHeaders();
......@@ -48,19 +64,23 @@ public class TestcaseServiceImpl extends ServiceImpl<TestcaseMapper, Testcase> i
String extract = testcase.getExtract();
String validate = testcase.getValidate();
// 参数准备
Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class);
Map<String, String> headersMap = JSON.parseObject(headers, Map.class);
if (variables != null && !variables.isEmpty() && parameters != null && !parameters.isEmpty()) {
parameterMap = autoUtilsService.replaceParameters(parameters, variables);
}
if (variables != null && !variables.isEmpty() && headers != null && !headers.isEmpty()) {
headersMap = autoUtilsService.replaceParameters(headers, variables);
}
Map<String, String> parameterMap = JSON.parseObject(parameters, Map.class);
// 使用变量替换headers
// if (variables != null && !variables.isEmpty() && headers != null && !headers.isEmpty()) {
// headersMap = autoUtilsService.replaceHeaders(headers, variables);
// }
// // 使用变量替换参数
// if (variables != null && !variables.isEmpty() && parameters != null && !parameters.isEmpty()) {
// parameterMap = autoUtilsService.replaceParameters(parameters, variables);
// }
// 创建断言列表
List<Map> validateList = new ArrayList<>();
if (validate != null && !validate.isEmpty()) {
validateList = JSON.parseArray(validate, Map.class);
}
String response = "";
Long startTime = System.currentTimeMillis();
// 发起http请求
switch (method) {
case "GET":
......@@ -77,16 +97,65 @@ public class TestcaseServiceImpl extends ServiceImpl<TestcaseMapper, Testcase> i
log.info("暂不支持该请求方法:{}", method);
break;
}
Long endTime = System.currentTimeMillis();
Long elapsedTime = endTime - startTime;
log.info("用例:{}, 返回为:{}", testcaseName, response);
log.info("本次接口执行时间:{}", elapsedTime);
// 进行断言
boolean assertResult = true;
if (!validateList.isEmpty()) {
autoUtilsService.assertResponse(response, validateList);
assertResult = autoUtilsService.assertResponse(response, validateList);
}
// 解析响应
if (extract != null && !extract.isEmpty()) {
autoUtilsService.extractResponse(response, extract);
// if (extract != null && !extract.isEmpty()) {
// autoUtilsService.extractResponse(response, extract);
// }
Map<String, Object> map = new HashMap<>();
map.put("url", url);
map.put("name", testcaseName);
map.put("headers", headersMap);
map.put("parameters", parameterMap);
map.put("assertResult", assertResult);
map.put("response", JSON.parseObject(response, Map.class));
map.put("elapsedTime", elapsedTime);
// 插入测试报告
TestcaseReport testcaseReport = new TestcaseReport();
testcaseReport.setTestcaseId(testcaseId);
testcaseReport.setHeaders(JSON.toJSONString(headersMap));
testcaseReport.setParameters(JSON.toJSONString(parameterMap));
testcaseReport.setResponse(response);
testcaseReport.setValidate(validate);
if (assertResult) {
testcaseReport.setStatus("pass");
} else {
testcaseReport.setStatus("fail");
}
return response;
testcaseReport.setElapsedTime(elapsedTime);
testcaseReport.setBatch(batch);
testcaseReport.setModuleId(testcase.getModuleId());
testcaseReport.setNamespace(namespace);
testcaseReportService.save(testcaseReport);
return JSON.toJSONString(map);
}
/**
* 执行某个模块下所有用例
* @param namespace 环境
* @param moduleId 模块id
* @param batch 执行批次
* @return
*/
@Override
public String executeTestcaseByModuleId(String namespace, Integer moduleId, String batch) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("module_id", moduleId);
List<Testcase> testcaseList = testcaseMapper.selectList(queryWrapper);
List<Map> resultList = new ArrayList<>();
for (Testcase testcase: testcaseList) {
String response = singleTestcaseExecutor(namespace, testcase.getId(), batch);
resultList.add(JSON.parseObject(response, Map.class));
}
return JSON.toJSONString(resultList);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment