提交 17bb0102 authored 作者: 黄夏豪's avatar 黄夏豪

feat(web): 新增了执行历史相关的接口

refactor(base):优化了执行器对外部执行的接口 方便其他外部调用
上级 3c7867f9
...@@ -42,7 +42,6 @@ import java.util.stream.Collectors; ...@@ -42,7 +42,6 @@ import java.util.stream.Collectors;
@Component @Component
public class HttpClientActuator implements Actuator { public class HttpClientActuator implements Actuator {
final final
CloseableHttpClient client; CloseableHttpClient client;
......
...@@ -66,7 +66,6 @@ public class CompleteExpressionUtil { ...@@ -66,7 +66,6 @@ public class CompleteExpressionUtil {
* @return jsonpath解析结果 * @return jsonpath解析结果
*/ */
public String completeJsonPathExpression(String expression, Object jsonObject) { public String completeJsonPathExpression(String expression, Object jsonObject) {
String result = expression; String result = expression;
result = regexExpression(result, JSON_PATH_REG, result = regexExpression(result, JSON_PATH_REG,
jsonObject, (o, s) -> JSON.toJSONString(JsonPath.read(o, s.substring(1, s.length() - 1)))); jsonObject, (o, s) -> JSON.toJSONString(JsonPath.read(o, s.substring(1, s.length() - 1))));
...@@ -89,6 +88,4 @@ public class CompleteExpressionUtil { ...@@ -89,6 +88,4 @@ public class CompleteExpressionUtil {
return SpringUtils.getBean("sqlExpActuator"); return SpringUtils.getBean("sqlExpActuator");
} }
} }
package org.matrix.config; package org.matrix.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.boot.autoconfigure.cache.CacheProperties; import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
...@@ -32,5 +35,4 @@ public class CacheConfig { ...@@ -32,5 +35,4 @@ public class CacheConfig {
return caffeineCacheManager; return caffeineCacheManager;
} }
} }
package org.matrix.config; package org.matrix.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.matrix.socket.HttpAuthHandler; import org.matrix.socket.HttpAuthHandler;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer; import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
......
package org.matrix.database.controller; package org.matrix.database.controller;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.matrix.actuators.usecase.CaseActuator; import org.matrix.actuators.usecase.CaseActuator;
import org.matrix.actuators.usecase.TestCaseExecuteResult; import org.matrix.actuators.usecase.TestCaseExecuteResult;
import org.matrix.database.entity.TestCase; import org.matrix.database.entity.TestCase;
import org.matrix.database.entity.TestCaseBTO; import org.matrix.database.entity.TestCaseBTO;
import org.matrix.database.entity.TestData; import org.matrix.database.entity.TestData;
import org.matrix.database.mapper.ExecutionHistoryMapper;
import org.matrix.database.service.IExecutionHistoryService;
import org.matrix.database.vo.ExecutionHistoryVo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -24,6 +29,9 @@ public class TestController { ...@@ -24,6 +29,9 @@ public class TestController {
@Autowired @Autowired
CaseActuator caseActuator; CaseActuator caseActuator;
@Autowired
IExecutionHistoryService executionHistoryService;
/** /**
* 获得表名,用于测试http执行器的调用 * 获得表名,用于测试http执行器的调用
*/ */
......
...@@ -46,4 +46,6 @@ public class Action extends BaseEntity { ...@@ -46,4 +46,6 @@ public class Action extends BaseEntity {
@ApiModelProperty("环境参数id") @ApiModelProperty("环境参数id")
private Long envId; private Long envId;
} }
package org.matrix.database.entity; package org.matrix.database.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.matrix.enums.ExecutionHistoryStatus;
/** /**
* <p> * <p>
...@@ -17,7 +19,8 @@ import lombok.NoArgsConstructor; ...@@ -17,7 +19,8 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@ApiModel(value = "") @ApiModel(value = "")
public class KtExecutionHistory extends BaseEntity { @TableName(value = "kt_execution_history")
public class ExecutionHistory extends BaseEntity {
private String unionKey; private String unionKey;
...@@ -27,12 +30,8 @@ public class KtExecutionHistory extends BaseEntity { ...@@ -27,12 +30,8 @@ public class KtExecutionHistory extends BaseEntity {
private Long jobId; private Long jobId;
private Integer status; private ExecutionHistoryStatus status = ExecutionHistoryStatus.READY;
private String caseName;
private String dataName;
private String jobName;
} }
...@@ -37,9 +37,6 @@ public class ExecutionRecord extends BaseEntity { ...@@ -37,9 +37,6 @@ public class ExecutionRecord extends BaseEntity {
@ApiModelProperty("key用来记录执行批次") @ApiModelProperty("key用来记录执行批次")
private String unionKey; private String unionKey;
@ApiModelProperty("执行状态,0:关闭,1:开启")
private ExecutionRecType status = ExecutionRecType.RUN;
@ApiModelProperty("类型") @ApiModelProperty("类型")
private TestExecuteType type; private TestExecuteType type;
......
package org.matrix.database.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Select;
import org.matrix.database.entity.ExecutionHistory;
import org.matrix.database.vo.ExecutionHistoryVo;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author mry
* @since 2022-03-11
*/
@Repository
public interface ExecutionHistoryMapper extends BaseMapper<ExecutionHistory> {
/**
* 根据CaseId和JobId 查询对应的数据列表
* @param page 分页数据
* @param jobId 测试任务ID
* @param caseId 用例ID
* @return 执行记录列表
*/
@Select("<script>" +
"SELECT\n" +
"\tkeh.id,\n" +
"\tkeh.union_key unionKey,\n" +
"\tkeh.case_id caseId,\n" +
"\tkeh.data_id dataId,\n" +
"\tkeh.job_id jobId,\n" +
"\tkeh.`status` `status`,\n" +
"\tktc.`name` caseName,\n" +
"\tktd.`name` dataName \n" +
"FROM\n" +
"\tkt_execution_history keh\n" +
"\tLEFT JOIN kt_test_case ktc ON ktc.id = keh.case_id\n" +
"\tLEFT JOIN kt_test_data ktd ON ktd.id = keh.data_id" +
"<where>" +
"<if test=\"caseId!=null\">\n" +
"and keh.case_id= #{caseId} \n" +
" </if>" +
"<if test=\"jobId!=null\">\n" +
"and keh.job_id= #{jobId} \n" +
" </if>" +
"</where>" +
"</script>")
IPage<ExecutionHistoryVo> pageByCaseIdAndJobId(IPage<ExecutionHistoryVo> page, Long caseId, Long jobId);
}
package org.matrix.database.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.matrix.database.entity.KtExecutionHistory;
import org.springframework.stereotype.Repository;
/**
* <p>
* Mapper 接口
* </p>
*
* @author mry
* @since 2022-03-11
*/
@Repository
public interface KtExecutionHistoryMapper extends BaseMapper<KtExecutionHistory> {
}
package org.matrix.database.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.matrix.database.entity.ExecutionHistory;
import org.matrix.database.vo.ExecutionHistoryVo;
import org.springframework.web.bind.annotation.RequestParam;
/**
* <p>
* 服务类
* </p>
*
* @author mry
* @since 2022-03-11
*/
public interface IExecutionHistoryService extends IService<ExecutionHistory> {
/**
* 根据CaseId和JobId 查询对应的数据列表
* @param pageNum 页码
* @param pageSize 分页条数
* @param jobId 测试任务ID
* @param caseId 用例ID
* @return 执行记录列表
*/
IPage<ExecutionHistoryVo> pageByCaseIdAndJobId( Long caseId, Long jobId,int pageSize, int pageNum);
}
package org.matrix.database.service;
import com.baomidou.mybatisplus.extension.service.IService;
import org.matrix.database.entity.KtExecutionHistory;
/**
* <p>
* 服务类
* </p>
*
* @author mry
* @since 2022-03-11
*/
public interface IKtExecutionHistoryService extends IService<KtExecutionHistory> {
}
package org.matrix.database.service.impl;
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.matrix.database.entity.ExecutionHistory;
import org.matrix.database.mapper.ExecutionHistoryMapper;
import org.matrix.database.service.IExecutionHistoryService;
import org.matrix.database.vo.ExecutionHistoryVo;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author mry
* @since 2022-03-11
*/
@Service
public class ExecutionHistoryServiceImpl extends ServiceImpl<ExecutionHistoryMapper, ExecutionHistory> implements IExecutionHistoryService {
@Override
public IPage<ExecutionHistoryVo> pageByCaseIdAndJobId(Long caseId, Long jobId, int pageNum,int pageSize ) {
Page<ExecutionHistoryVo> page = new Page<>(pageNum, pageSize);
return baseMapper.pageByCaseIdAndJobId(page,caseId,jobId);
}
}
package org.matrix.database.service.impl; package org.matrix.database.service.impl;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.matrix.actuators.datasource.IDataSourceService;
import org.matrix.database.entity.ExecutionRecord; import org.matrix.database.entity.ExecutionRecord;
import org.matrix.database.mapper.ExecutionRecordMapper; import org.matrix.database.mapper.ExecutionRecordMapper;
import org.matrix.database.service.IExecutionRecordService; import org.matrix.database.service.IExecutionRecordService;
import org.matrix.enums.ExecutionRecType; import org.matrix.enums.ExecutionRecType;
import org.matrix.exception.GlobalException; import org.matrix.exception.GlobalException;
import org.matrix.socket.TestExecuteLog; import org.matrix.socket.TestExecuteLog;
import org.matrix.socket.TestExecuteType;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/** /**
* @author mry * @author mry
*/ */
@Service @Service
public class ExecutionRecordImpl extends ServiceImpl<ExecutionRecordMapper, ExecutionRecord> implements IExecutionRecordService { public class ExecutionRecordImpl extends ServiceImpl<ExecutionRecordMapper, ExecutionRecord> implements IExecutionRecordService {
@Autowired
IDataSourceService iDataSourceService;
@Override @Override
public void addExecutionRecord(TestExecuteLog testExecuteLog,String log) { public void addExecutionRecord(TestExecuteLog testExecuteLog,String log) {
ExecutionRecord executionRecord = new ExecutionRecord(); ExecutionRecord executionRecord = new ExecutionRecord();
...@@ -39,7 +40,6 @@ public class ExecutionRecordImpl extends ServiceImpl<ExecutionRecordMapper, Exec ...@@ -39,7 +40,6 @@ public class ExecutionRecordImpl extends ServiceImpl<ExecutionRecordMapper, Exec
throw new GlobalException("不能根据空的unionKey修改执行状态"); throw new GlobalException("不能根据空的unionKey修改执行状态");
}else { }else {
ExecutionRecord executionRecord = new ExecutionRecord(); ExecutionRecord executionRecord = new ExecutionRecord();
executionRecord.setStatus(status);
update(executionRecord,Wrappers update(executionRecord,Wrappers
.lambdaUpdate(ExecutionRecord.class) .lambdaUpdate(ExecutionRecord.class)
.eq(ExecutionRecord::getUnionKey,unionKey) .eq(ExecutionRecord::getUnionKey,unionKey)
......
package org.matrix.database.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.matrix.database.entity.KtExecutionHistory;
import org.matrix.database.mapper.KtExecutionHistoryMapper;
import org.matrix.database.service.IKtExecutionHistoryService;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author mry
* @since 2022-03-11
*/
@Service
public class KtExecutionHistoryServiceImpl extends ServiceImpl<KtExecutionHistoryMapper, KtExecutionHistory> implements IKtExecutionHistoryService {
}
package org.matrix.database.vo;
import lombok.Data;
import org.matrix.database.entity.ExecutionHistory;
/**
* ExecutionHistory 给前端用于展示的VO
* @author huangxiahao
*/
@Data
public class ExecutionHistoryVo extends ExecutionHistory {
private String caseName;
private String dataName;
}
package org.matrix.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 执行历史中的执行状态
* @author huangxiahao
*/
@Getter
@AllArgsConstructor
public enum ExecutionHistoryStatus {
/**
* SQL类型动作,该动作执行SQL语句
*/
READY(0, "准备阶段"),
/**
* HTTP类型动作,该动作执行HTTP接口
*/
RUN(1, "执行阶段"),
/**
* 用例类型动作,该动作执行另外的测试用例
*/
FINISH(2, "完成阶段");
/**
* 数据库里记录的字段使用该字段来记录
*/
@EnumValue
private final int code;
private final String des;
}
...@@ -15,11 +15,13 @@ public class CaseExecuteVo extends SocketVo { ...@@ -15,11 +15,13 @@ public class CaseExecuteVo extends SocketVo {
private TestExecuteType type = TestExecuteType.TEST_CASE; private TestExecuteType type = TestExecuteType.TEST_CASE;
private Long userId; private Long userId = -1L;
private Long projectId; private Long projectId = -1L;
private Long envId; private Long envId = -1L;
private Long jobId = -1L ;
private List<TestCaseListDataBto> testCaseListDataBtoList; private List<TestCaseListDataBto> testCaseListDataBtoList;
} }
...@@ -3,8 +3,6 @@ package org.matrix.socket; ...@@ -3,8 +3,6 @@ package org.matrix.socket;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONException;
import org.matrix.actuators.usecase.CaseActuator; import org.matrix.actuators.usecase.CaseActuator;
import org.matrix.actuators.util.ThreadUtil;
import org.matrix.database.entity.TestCaseListDataBto;
import org.matrix.database.service.ITestDataService; import org.matrix.database.service.ITestDataService;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
...@@ -12,9 +10,6 @@ import org.springframework.web.socket.TextMessage; ...@@ -12,9 +10,6 @@ import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler; import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.util.List;
import java.util.UUID;
/** /**
* webSocket处理 * webSocket处理
* *
...@@ -26,26 +21,34 @@ public class HttpAuthHandler extends TextWebSocketHandler { ...@@ -26,26 +21,34 @@ public class HttpAuthHandler extends TextWebSocketHandler {
final CaseActuator caseActuator; final CaseActuator caseActuator;
final ITestDataService testDataService; final ITestDataService testDataService;
public HttpAuthHandler(CaseActuator caseActuator, ITestDataService testDataService) { public HttpAuthHandler(CaseActuator caseActuator, ITestDataService testDataService) {
this.caseActuator = caseActuator; this.caseActuator = caseActuator;
this.testDataService = testDataService; this.testDataService = testDataService;
} }
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
super.afterConnectionEstablished(session);
System.out.println("连接成功了");
}
@Override @Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("收到了: " + message.toString());
session.sendMessage(new TextMessage("message get success")); session.sendMessage(new TextMessage("message get success"));
String payload = message.getPayload(); String payload = message.getPayload();
//检验客户端是否进行测试用例调试 //检验客户端是否进行测试用例调试
try { try {
SocketVo socketVo = JSON.parseObject(payload, SocketVo.class); SocketVo socketVo = JSON.parseObject(payload, SocketVo.class);
//如果客户端发送测试用例调试命令,则进行测试用例的执行 //如果客户端发送测试用例调试命令,则进行测试用例的执行
if (socketVo != null && socketVo.getSocketType()!=null) { if (socketVo != null && socketVo.getSocketType() != null) {
if (SocketType.TEST_CASE_EXECUTE.equals(socketVo.getSocketType())) { if (SocketType.TEST_CASE_EXECUTE.equals(socketVo.getSocketType())) {
runTestCase(session, payload); CaseExecuteVo caseExecuteVo = JSON.parseObject(payload, CaseExecuteVo.class);
}else if (SocketType.TEST_CASE_MONITOR.equals(socketVo.getSocketType())){ caseActuator.runTestCase(session, caseExecuteVo);
} else if (SocketType.TEST_CASE_MONITOR.equals(socketVo.getSocketType())) {
ExecuteMonitorVo caseExecuteVo = JSON.parseObject(payload, ExecuteMonitorVo.class); ExecuteMonitorVo caseExecuteVo = JSON.parseObject(payload, ExecuteMonitorVo.class);
ExecuteMonitorSocketPool.add(caseExecuteVo.getUnionKey(),session); ExecuteMonitorSocketPool.add(caseExecuteVo.getUnionKey(), session);
} else { } else {
session.sendMessage(new TextMessage("入参不符合规定")); session.sendMessage(new TextMessage("入参不符合规定"));
} }
...@@ -61,30 +64,6 @@ public class HttpAuthHandler extends TextWebSocketHandler { ...@@ -61,30 +64,6 @@ public class HttpAuthHandler extends TextWebSocketHandler {
ExecuteMonitorSocketPool.remove(session); ExecuteMonitorSocketPool.remove(session);
} }
/**
* 执行TestCase,并控制运行态日志池,进行日志的生成。
*/
private void runTestCase(WebSocketSession session, String payload) {
//将websocketSession 加入到socket池子中
Long currentThreadId = ThreadUtil.currentThreadId();
TestCaseExecuteSocketPool.add(currentThreadId, session);
CaseExecuteVo caseExecuteVo = JSON.parseObject(payload, CaseExecuteVo.class);
List<TestCaseListDataBto> testCaseListDataBtoList = caseExecuteVo.getTestCaseListDataBtoList();
String unionKey = UUID.randomUUID().toString();
for (TestCaseListDataBto testCaseListDataBto : testCaseListDataBtoList) {
LogQueueRuntime
.initTestCaseLog(caseExecuteVo.getUserId()
,testCaseListDataBto.getTestCase().getId()
, caseExecuteVo.getType()
, unionKey
);
//执行测试用例
caseActuator.executeTestCases(testCaseListDataBto, caseExecuteVo.getEnvId(), caseExecuteVo.getProjectId());
}
//将本次产生的数据清除
TestCaseExecuteSocketPool.remove(Thread.currentThread().getId());
//将本次产生的日志从执行状态设为停止状态
LogQueueRuntime.stopExecutionRecords(unionKey);
}
} }
...@@ -11,7 +11,6 @@ import org.matrix.util.SpringUtils; ...@@ -11,7 +11,6 @@ import org.matrix.util.SpringUtils;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.WebSocketSession;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
...@@ -38,10 +37,6 @@ public class LogQueueRuntime { ...@@ -38,10 +37,6 @@ public class LogQueueRuntime {
getExecutionRecordService().addExecutionRecord(testExecuteLog,log); getExecutionRecordService().addExecutionRecord(testExecuteLog,log);
} }
public static void stopExecutionRecords(String unionKey){
getExecutionRecordService().setStatusByUnionKey(unionKey,ExecutionRecType.STOP);
}
/** /**
* 如果返回false,表示该用例已经在线程中执行了 * 如果返回false,表示该用例已经在线程中执行了
...@@ -73,20 +68,21 @@ public class LogQueueRuntime { ...@@ -73,20 +68,21 @@ public class LogQueueRuntime {
} }
public static void remove(Long threadId) { public static void remove(Long threadId) {
TestCaseExecuteSocketPool.remove(threadId); LOG_MAP.remove(threadId);
} }
public static void sendMessage(Long threadId,String unionKey, Object log) { public static void sendMessage(Long threadId,String unionKey, Object log) {
try { try {
TestExecuteLog testExecuteLog = LOG_MAP.get(threadId); TestExecuteLog testExecuteLog = LOG_MAP.get(threadId);
// 测试任务ID.测试用例ID.测试数据ID // 测试任务ID.测试用例ID.测试数据ID
String message = JSONObject.toJSONString(log);
String logMessage = String logMessage =
String.format( String.format(
"%s.%s.%s.%s" "%s.%s.%s.%s"
,testExecuteLog.getTestJobId() ,testExecuteLog.getJobId()
,testExecuteLog.getTestCaseId() ,testExecuteLog.getTestCaseId()
,testExecuteLog.getTestDataId() ,testExecuteLog.getTestDataId()
,JSONObject.toJSONString(log) ,message.substring(1,message.length()-1)
); );
//如果unionKey中存在监听的socket则向该socket发送消息 //如果unionKey中存在监听的socket则向该socket发送消息
List<WebSocketSession> webSocketSessions = ExecuteMonitorSocketPool.get(unionKey); List<WebSocketSession> webSocketSessions = ExecuteMonitorSocketPool.get(unionKey);
...@@ -110,13 +106,30 @@ public class LogQueueRuntime { ...@@ -110,13 +106,30 @@ public class LogQueueRuntime {
} }
} }
public static void initTestCaseLog(Long userId, Long caseId,TestExecuteType type,String unionKey) { public static void initTestCaseLog(Long jobId,Long userId, Long caseId,TestExecuteType type,String unionKey) {
TestExecuteLog testExecuteLog = new TestExecuteLog(); TestExecuteLog testExecuteLog = new TestExecuteLog();
testExecuteLog.setJobId(jobId);
testExecuteLog.setTestCaseId(caseId); testExecuteLog.setTestCaseId(caseId);
testExecuteLog.setUserId(userId); testExecuteLog.setUserId(userId);
testExecuteLog.setType(type); testExecuteLog.setType(type);
testExecuteLog.setUnionKey(unionKey); testExecuteLog.setUnionKey(unionKey);
if (checkIsInRun(testExecuteLog)){
throw new GlobalException("当前用例正在执行中");
}
LogQueueRuntime.put(ThreadUtil.currentThreadId(), testExecuteLog); LogQueueRuntime.put(ThreadUtil.currentThreadId(), testExecuteLog);
} }
public static Boolean checkIsInRun(TestExecuteLog testExecuteLog){
for (TestExecuteLog value : LOG_MAP.values()) {
if (value.equals(testExecuteLog)){
return true;
}
}
return false;
}
public static TestExecuteLog getCurrentTestExecute(Long threadId){
return LOG_MAP.get(threadId);
}
} }
...@@ -4,6 +4,7 @@ import lombok.Data; ...@@ -4,6 +4,7 @@ import lombok.Data;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* 用例日志临时存储对象 * 用例日志临时存储对象
...@@ -13,15 +14,15 @@ import java.util.List; ...@@ -13,15 +14,15 @@ import java.util.List;
public class TestExecuteLog { public class TestExecuteLog {
private Long testJobId = -1L; private Long jobId = -1L;
/** /**
* 用于记录执行记录的唯一KEY,同一批次的执行记录应该具有相同的KEY。 * 用于记录执行记录的唯一KEY,同一批次的执行记录应该具有相同的KEY。
*/ */
private String unionKey; private String unionKey;
private TestExecuteType type; private TestExecuteType type = TestExecuteType.TEST_CASE;
private Long userId; private Long userId = -1L ;
private Long testCaseId = -1L; private Long testCaseId = -1L;
...@@ -38,5 +39,20 @@ public class TestExecuteLog { ...@@ -38,5 +39,20 @@ public class TestExecuteLog {
this.log.add(log); this.log.add(log);
} }
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof TestExecuteLog)) {
return false;
}
TestExecuteLog that = (TestExecuteLog) o;
return getType() == that.getType() && Objects.equals(getUserId(), that.getUserId()) && Objects.equals(getTestCaseId(), that.getTestCaseId());
}
@Override
public int hashCode() {
return Objects.hash(getType(), getUserId(), getTestCaseId());
}
} }
...@@ -66,6 +66,9 @@ public class TestPigeon extends AbstractTestNGSpringContextTests { ...@@ -66,6 +66,9 @@ public class TestPigeon extends AbstractTestNGSpringContextTests {
@Autowired @Autowired
private HttpClientActuator httpClientActuator; private HttpClientActuator httpClientActuator;
@Autowired
private CaseActuator caseActuator;
@Parameters({"sql", "envId", "projectId"}) @Parameters({"sql", "envId", "projectId"})
@BeforeClass @BeforeClass
public void beforeClass(String sql, Long envId, Long projectId) { public void beforeClass(String sql, Long envId, Long projectId) {
...@@ -84,18 +87,19 @@ public class TestPigeon extends AbstractTestNGSpringContextTests { ...@@ -84,18 +87,19 @@ public class TestPigeon extends AbstractTestNGSpringContextTests {
@Test(dataProvider = "testData") @Test(dataProvider = "testData")
public void test(Map<String, String> data) { public void test(Map<String, String> data) {
//todo 黄夏豪 这里的调用接口我改掉了 等我改完了再喊你改
long caseId = Long.parseLong(data.get("id")); long caseId = Long.parseLong(data.get("id"));
CaseActuator caseActuator = new CaseActuator(checkPointActuator, httpClientActuator);
TestCase testCase = java.util.Optional.of(caseService.getById(caseId)) TestCase testCase = java.util.Optional.of(caseService.getById(caseId))
.orElseThrow(() -> new GlobalException(String.format("没有找到id = %d 的TestCase", caseId))); .orElseThrow(() -> new GlobalException(String.format("没有找到id = %d 的TestCase", caseId)));
List<TestData> testDataList = java.util.Optional.of(dataService.list(Wrappers.lambdaQuery(TestData.class) List<TestData> testDataList = java.util.Optional.of(dataService.list(Wrappers.lambdaQuery(TestData.class)
.eq(TestData::getTestCaseId, caseId))) .eq(TestData::getTestCaseId, caseId)))
.orElseThrow(() -> new GlobalException(String.format("没有找到testCaseId = %d 的TestData", caseId))); .orElseThrow(() -> new GlobalException(String.format("没有找到testCaseId = %d 的TestData", caseId)));
TestCaseBTO testCaseBTO = new TestCaseBTO(); TestCaseBTO testCaseBTO = new TestCaseBTO();
testCaseBTO.setTestCase(testCase); testCaseBTO.setTestCase(testCase);
String unionKey = UUID.randomUUID().toString(); String unionKey = UUID.randomUUID().toString();
LogQueueRuntime LogQueueRuntime
.initTestCaseLog(1L .initTestCaseLog(null
, 1L
, testCase.getId() , testCase.getId()
, TestExecuteType.TEST_CASE , TestExecuteType.TEST_CASE
, unionKey , unionKey
...@@ -108,8 +112,6 @@ public class TestPigeon extends AbstractTestNGSpringContextTests { ...@@ -108,8 +112,6 @@ public class TestPigeon extends AbstractTestNGSpringContextTests {
} }
//将本次产生的数据清除 //将本次产生的数据清除
TestCaseExecuteSocketPool.remove(Thread.currentThread().getId()); TestCaseExecuteSocketPool.remove(Thread.currentThread().getId());
//将本次产生的日志从执行状态设为停止状态
LogQueueRuntime.stopExecutionRecords(unionKey);
} }
@AfterMethod @AfterMethod
......
package org.matrix.actuators.sql; package org.matrix.actuators.http;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
......
...@@ -25,7 +25,7 @@ class MoveActuatorTest { ...@@ -25,7 +25,7 @@ class MoveActuatorTest {
@Test @Test
void runMoveSQL() { void runMoveSQL() {
LogQueueRuntime.initTestCaseLog(null, null, null, null); LogQueueRuntime.initTestCaseLog(null,null, null, null, null);
moveActuator.runMove(72L, 9L, 1L, null, MoveStrategy.PRE_MOVE); moveActuator.runMove(72L, 9L, 1L, null, MoveStrategy.PRE_MOVE);
String result = moveActuator.parseMoveVar("${pre72.url}[1]"); String result = moveActuator.parseMoveVar("${pre72.url}[1]");
Assertions.assertTrue(result.length() > 0, result); Assertions.assertTrue(result.length() > 0, result);
...@@ -33,7 +33,7 @@ class MoveActuatorTest { ...@@ -33,7 +33,7 @@ class MoveActuatorTest {
@Test @Test
void runMoveHTTP() { void runMoveHTTP() {
LogQueueRuntime.initTestCaseLog(null, null, null, null); LogQueueRuntime.initTestCaseLog(null,null, null, null, null);
moveActuator.runMove(72L, 10L, 1L, null, MoveStrategy.PRE_MOVE); moveActuator.runMove(72L, 10L, 1L, null, MoveStrategy.PRE_MOVE);
String result = moveActuator.parseMoveVar("${pre72.responseBody}<$.data.records[1].name>"); String result = moveActuator.parseMoveVar("${pre72.responseBody}<$.data.records[1].name>");
Assertions.assertTrue(result.length() > 0, result); Assertions.assertTrue(result.length() > 0, result);
......
package org.matrix.autotest.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.matrix.autotest.utils.PageTools;
import org.matrix.database.entity.ExecutionRecord;
import org.matrix.database.service.IExecutionHistoryService;
import org.matrix.database.service.IExecutionRecordService;
import org.matrix.database.vo.CommonResult;
import org.matrix.database.vo.CommonResultObj;
import org.matrix.database.vo.ExecutionHistoryVo;
import org.matrix.enums.ExecutionRecType;
import org.matrix.socket.TestExecuteType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
/**
* @author hxh
*/
@CrossOrigin
@RestController
@RequestMapping("/executionHistory")
@Api(tags = "对执行历史execution_history的基本操作")
public class ExecutionHistoryController {
private final IExecutionHistoryService executionHistoryService;
public ExecutionHistoryController(IExecutionHistoryService executionHistoryService) {
this.executionHistoryService = executionHistoryService;
}
@GetMapping("/findExecutionHistory")
public ResponseEntity<CommonResultObj<IPage<ExecutionHistoryVo>>> findExecutionHistory(
@RequestParam(defaultValue = "10") int pageSize,
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "-1") Long jobId,
Long caseId
){
IPage<ExecutionHistoryVo> page = executionHistoryService.pageByCaseIdAndJobId(caseId, jobId, pageNum, pageSize);
return page.getRecords().size() != 0
? CommonResult.success(page, "查询成功")
: CommonResult.failed(page, "查询失败或无数据");
}
}
...@@ -62,7 +62,6 @@ public class ExecutionRecordController { ...@@ -62,7 +62,6 @@ public class ExecutionRecordController {
.eq(testDataId != null, ExecutionRecord::getTestDataId, testDataId) .eq(testDataId != null, ExecutionRecord::getTestDataId, testDataId)
.eq(testCaseId != null, ExecutionRecord::getTestCaseId, testCaseId) .eq(testCaseId != null, ExecutionRecord::getTestCaseId, testCaseId)
.eq(StringUtils.hasLength(unionKey), ExecutionRecord::getUnionKey, unionKey) .eq(StringUtils.hasLength(unionKey), ExecutionRecord::getUnionKey, unionKey)
.eq(status != null, ExecutionRecord::getStatus, status)
.eq(type != null, ExecutionRecord::getType, type) .eq(type != null, ExecutionRecord::getType, type)
)).orElse(new Page<>()); )).orElse(new Page<>());
PageTools.pageTool(pageSize, pageNum, results); PageTools.pageTool(pageSize, pageNum, results);
......
...@@ -71,11 +71,14 @@ public class TestCaseController { ...@@ -71,11 +71,14 @@ public class TestCaseController {
@RequestParam(defaultValue = "10") int pageSize, @RequestParam(defaultValue = "10") int pageSize,
@RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "1") int pageNum,
String name, @PathVariable Long projectId) { String name, @PathVariable Long projectId) {
final long start = System.currentTimeMillis();
Page<TestCase> results = Optional.ofNullable(testCaseService.page(Page.of(pageNum, pageSize) Page<TestCase> results = Optional.ofNullable(testCaseService.page(Page.of(pageNum, pageSize)
, Wrappers.lambdaQuery(TestCase.class).eq(TestCase::getProjectId, projectId) , Wrappers.lambdaQuery(TestCase.class).eq(TestCase::getProjectId, projectId)
.like(StringUtils.hasLength(name) .like(StringUtils.hasLength(name)
, TestCase::getName, name))).orElse(new Page<>()); , TestCase::getName, name))).orElse(new Page<>());
PageTools.pageTool(pageSize, pageNum, results); PageTools.pageTool(pageSize, pageNum, results);
System.out.println(System.currentTimeMillis() - start);
return results.getRecords().size() != 0 return results.getRecords().size() != 0
? CommonResult.success(results, "查询成功") ? CommonResult.success(results, "查询成功")
: CommonResult.failed(results, "查询失败或无数据"); : CommonResult.failed(results, "查询失败或无数据");
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论