refactor(接口测试): 执行结果处理优化,嵌套事务拆分成小事务
--story=1010710 --user=赵勇 【bug转需求】优化消息通知机制(同步发1.20) https://www.tapd.cn/55049933/s/1315550
This commit is contained in:
parent
0f174ae73e
commit
22eecf4335
|
@ -535,7 +535,7 @@
|
|||
<artifactItem>
|
||||
<groupId>org.python</groupId>
|
||||
<artifactId>jython-standalone</artifactId>
|
||||
<version>2.7.2</version>
|
||||
<version>2.7.0</version>
|
||||
<type>jar</type>
|
||||
<overWrite>true</overWrite>
|
||||
<outputDirectory>src/main/resources/jmeter/lib/ext</outputDirectory>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.metersphere.api.dto.QueryAPIReportRequest;
|
||||
import io.metersphere.api.dto.RequestResultExpandDTO;
|
||||
import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult;
|
||||
|
@ -9,13 +8,15 @@ import io.metersphere.base.domain.*;
|
|||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
|
||||
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
|
||||
import io.metersphere.commons.constants.*;
|
||||
import io.metersphere.commons.utils.*;
|
||||
import io.metersphere.controller.request.OrderRequest;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
import io.metersphere.commons.constants.ExecuteResult;
|
||||
import io.metersphere.commons.constants.TriggerMode;
|
||||
import io.metersphere.commons.utils.DateUtils;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.ResponseUtil;
|
||||
import io.metersphere.commons.utils.ServiceUtils;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import io.metersphere.dto.ResultDTO;
|
||||
import io.metersphere.notice.sender.NoticeModel;
|
||||
import io.metersphere.notice.service.NoticeSendService;
|
||||
import io.metersphere.track.dto.PlanReportCaseDTO;
|
||||
import io.metersphere.track.dto.TestPlanDTO;
|
||||
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
|
||||
|
@ -23,7 +24,6 @@ import io.metersphere.track.request.testcase.TrackCount;
|
|||
import io.metersphere.track.service.TestCaseReviewApiCaseService;
|
||||
import io.metersphere.track.service.TestPlanTestCaseService;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import org.apache.commons.beanutils.BeanMap;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -58,51 +58,35 @@ public class ApiDefinitionExecResultService {
|
|||
@Resource
|
||||
private TestCaseReviewApiCaseMapper testCaseReviewApiCaseMapper;
|
||||
@Resource
|
||||
private NoticeSendService noticeSendService;
|
||||
@Resource
|
||||
private TestPlanTestCaseService testPlanTestCaseService;
|
||||
@Resource
|
||||
private ApiTestCaseService apiTestCaseService;
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private SqlSessionFactory sqlSessionFactory;
|
||||
|
||||
public void saveApiResult(ResultDTO dto) {
|
||||
public List<ApiDefinitionExecResult> saveApiResult(ResultDTO dto) {
|
||||
LoggerUtil.info("接收到API/CASE执行结果【 " + dto.getRequestResults().size() + " 】条");
|
||||
|
||||
List<ApiDefinitionExecResult> results = new LinkedList<>();
|
||||
for (RequestResult item : dto.getRequestResults()) {
|
||||
if (item.getResponseResult() != null && item.getResponseResult().getResponseTime() <= 0) {
|
||||
item.getResponseResult().setResponseTime((item.getEndTime() - item.getStartTime()));
|
||||
}
|
||||
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
|
||||
ApiDefinitionExecResult result = this.editResult(item, dto.getReportId(), dto.getConsole(), dto.getRunMode(), dto.getTestId(), null);
|
||||
if (result != null) {
|
||||
User user = null;
|
||||
if (MapUtils.isNotEmpty(dto.getExtendedParameters())) {
|
||||
if (dto.getExtendedParameters().containsKey("userId") && dto.getExtendedParameters().containsKey("userName")) {
|
||||
user = new User() {{
|
||||
this.setId(dto.getExtendedParameters().get("userId").toString());
|
||||
this.setName(dto.getExtendedParameters().get("userName").toString());
|
||||
}};
|
||||
} else if (dto.getExtendedParameters().containsKey("userId")) {
|
||||
result.setUserId(dto.getExtendedParameters().get("userId").toString());
|
||||
}
|
||||
}
|
||||
// 发送通知
|
||||
if (result != null && !StringUtils.startsWithAny(dto.getRunMode(), "SCHEDULE","API_PLAN")) {
|
||||
result.setResourceId(dto.getTestId());
|
||||
LoggerUtil.info("执行结果【 " + result.getName() + " 】入库存储完成");
|
||||
sendNotice(result, user);
|
||||
results.add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public void batchSaveApiResult(List<ResultDTO> resultDTOS, boolean isSchedule) {
|
||||
public Map<ResultDTO, List<ApiDefinitionExecResult>> batchSaveApiResult(List<ResultDTO> resultDTOS, boolean isSchedule) {
|
||||
Map<ResultDTO, List<ApiDefinitionExecResult>> results = new HashMap<>();
|
||||
if (CollectionUtils.isEmpty(resultDTOS)) {
|
||||
return;
|
||||
return results;
|
||||
}
|
||||
LoggerUtil.info("接收到API/CASE执行结果【 " + resultDTOS.size() + " 】");
|
||||
|
||||
|
@ -111,8 +95,8 @@ public class ApiDefinitionExecResultService {
|
|||
TestPlanApiCaseMapper planApiCaseMapper = sqlSession.getMapper(TestPlanApiCaseMapper.class);
|
||||
TestCaseReviewApiCaseMapper reviewApiCaseMapper = sqlSession.getMapper(TestCaseReviewApiCaseMapper.class);
|
||||
ApiTestCaseMapper batchApiTestCaseMapper = sqlSession.getMapper(ApiTestCaseMapper.class);
|
||||
|
||||
for (ResultDTO dto : resultDTOS) {
|
||||
List<ApiDefinitionExecResult> resultList = new LinkedList<>();
|
||||
if (CollectionUtils.isNotEmpty(dto.getRequestResults())) {
|
||||
for (RequestResult item : dto.getRequestResults()) {
|
||||
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
|
||||
|
@ -123,78 +107,27 @@ public class ApiDefinitionExecResultService {
|
|||
planApiCaseMapper, reviewApiCaseMapper, batchApiTestCaseMapper
|
||||
);
|
||||
|
||||
if (result != null && !StringUtils.startsWithAny(dto.getRunMode(), "SCHEDULE")) {
|
||||
User user = null;
|
||||
if (MapUtils.isNotEmpty(dto.getExtendedParameters()) && dto.getExtendedParameters().containsKey("user") && dto.getExtendedParameters().get("user") instanceof User) {
|
||||
user = (User) dto.getExtendedParameters().get("user");
|
||||
} else if (MapUtils.isNotEmpty(dto.getExtendedParameters()) && dto.getExtendedParameters().containsKey("userId")) {
|
||||
result.setUserId(String.valueOf(dto.getExtendedParameters().get("userId")));
|
||||
}
|
||||
if (result != null && !StringUtils.startsWithAny(dto.getRunMode(), "SCHEDULE","API_PLAN")) {
|
||||
// 发送通知
|
||||
result.setResourceId(dto.getTestId());
|
||||
sendNotice(result, user);
|
||||
resultList.add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isSchedule) {
|
||||
// 这个方法得优化大批量跑有问题
|
||||
updateTestCaseStates(dto.getTestId());
|
||||
Map<String, String> apiIdResultMap = new HashMap<>();
|
||||
long errorSize = dto.getRequestResults().stream().filter(requestResult -> requestResult.getError() > 0).count();
|
||||
String status = errorSize > 0 || dto.getRequestResults().isEmpty() ? TestPlanApiExecuteStatus.FAILD.name() : TestPlanApiExecuteStatus.SUCCESS.name();
|
||||
if (StringUtils.isNotEmpty(dto.getReportId())) {
|
||||
apiIdResultMap.put(dto.getReportId(), status);
|
||||
}
|
||||
LoggerUtil.info("TestPlanReportId[" + dto.getTestPlanReportId() + "] API CASE OVER. API CASE STATUS:" + JSONObject.toJSONString(apiIdResultMap));
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(resultList)) {
|
||||
results.put(dto, resultList);
|
||||
}
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
if (sqlSession != null && sqlSessionFactory != null) {
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendNotice(ApiDefinitionExecResult result, User user) {
|
||||
try {
|
||||
String resourceId = result.getResourceId();
|
||||
ApiTestCaseWithBLOBs apiTestCaseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(resourceId);
|
||||
// 接口定义直接执行不发通知
|
||||
if (apiTestCaseWithBLOBs == null) {
|
||||
return;
|
||||
}
|
||||
BeanMap beanMap = new BeanMap(apiTestCaseWithBLOBs);
|
||||
|
||||
String event;
|
||||
String status;
|
||||
if (StringUtils.equals(result.getStatus(), "success")) {
|
||||
event = NoticeConstants.Event.EXECUTE_SUCCESSFUL;
|
||||
status = "成功";
|
||||
} else {
|
||||
event = NoticeConstants.Event.EXECUTE_FAILED;
|
||||
status = "失败";
|
||||
}
|
||||
if (user == null && StringUtils.isNotBlank(result.getUserId())) {
|
||||
user = userMapper.selectByPrimaryKey(result.getUserId());
|
||||
}
|
||||
Map paramMap = new HashMap<>(beanMap);
|
||||
paramMap.put("operator", user != null ? user.getName() : result.getUserId());
|
||||
paramMap.put("status", result.getStatus());
|
||||
String context = "${operator}执行接口用例" + status + ": ${name}";
|
||||
NoticeModel noticeModel = NoticeModel.builder()
|
||||
.operator(result.getUserId() != null ? result.getUserId() : SessionUtils.getUserId())
|
||||
.context(context)
|
||||
.subject("接口用例通知")
|
||||
.paramMap(paramMap)
|
||||
.event(event)
|
||||
.build();
|
||||
|
||||
String taskType = NoticeConstants.TaskType.API_DEFINITION_TASK;
|
||||
Project project = projectMapper.selectByPrimaryKey(apiTestCaseWithBLOBs.getProjectId());
|
||||
noticeSendService.send(project, taskType, noticeModel);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("消息发送失败:" + e.getMessage());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public void setExecResult(String id, String status, Long time) {
|
||||
|
@ -336,12 +269,6 @@ public class ApiDefinitionExecResultService {
|
|||
}
|
||||
}
|
||||
updateTestCaseStates(dto.getTestId());
|
||||
Map<String, String> apiIdResultMap = new HashMap<>();
|
||||
long errorSize = dto.getRequestResults().stream().filter(requestResult -> requestResult.getError() > 0).count();
|
||||
String status = errorSize > 0 || dto.getRequestResults().isEmpty() ? TestPlanApiExecuteStatus.FAILD.name() : TestPlanApiExecuteStatus.SUCCESS.name();
|
||||
if (StringUtils.isNotEmpty(dto.getReportId())) {
|
||||
apiIdResultMap.put(dto.getReportId(), status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -507,30 +434,12 @@ public class ApiDefinitionExecResultService {
|
|||
}
|
||||
}
|
||||
|
||||
public ApiDefinitionExecResult getInfo(String id) {
|
||||
return apiDefinitionExecResultMapper.selectByPrimaryKey(id);
|
||||
}
|
||||
|
||||
public List<PlanReportCaseDTO> selectForPlanReport(List<String> apiReportIds) {
|
||||
if (CollectionUtils.isEmpty(apiReportIds))
|
||||
return new ArrayList<>();
|
||||
return extApiDefinitionExecResultMapper.selectForPlanReport(apiReportIds);
|
||||
}
|
||||
|
||||
private static List<OrderRequest> getDefaultOrderByField(String prefix, List<OrderRequest> orders, String field) {
|
||||
if (orders == null || orders.size() < 1) {
|
||||
OrderRequest orderRequest = new OrderRequest();
|
||||
orderRequest.setName(field);
|
||||
orderRequest.setType("desc");
|
||||
if (StringUtils.isNotBlank(prefix)) {
|
||||
orderRequest.setPrefix(prefix);
|
||||
}
|
||||
orders = new ArrayList<>();
|
||||
orders.add(orderRequest);
|
||||
return orders;
|
||||
}
|
||||
return orders;
|
||||
}
|
||||
|
||||
public List<ApiDefinitionExecResultExpand> apiReportList(QueryAPIReportRequest request) {
|
||||
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders(), "end_time"));
|
||||
|
|
|
@ -2,9 +2,7 @@ package io.metersphere.api.service;
|
|||
|
||||
import io.metersphere.api.dto.automation.ApiTestReportVariable;
|
||||
import io.metersphere.base.domain.*;
|
||||
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
|
||||
import io.metersphere.base.mapper.ApiScenarioMapper;
|
||||
import io.metersphere.base.mapper.UiScenarioMapper;
|
||||
import io.metersphere.base.mapper.*;
|
||||
import io.metersphere.commons.constants.APITestStatus;
|
||||
import io.metersphere.commons.constants.ApiRunMode;
|
||||
import io.metersphere.commons.constants.NoticeConstants;
|
||||
|
@ -12,11 +10,11 @@ import io.metersphere.commons.constants.ReportTriggerMode;
|
|||
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||
import io.metersphere.commons.utils.DateUtils;
|
||||
import io.metersphere.commons.utils.LogUtil;
|
||||
import io.metersphere.commons.utils.SessionUtils;
|
||||
import io.metersphere.constants.RunModeConstants;
|
||||
import io.metersphere.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.dto.RequestResult;
|
||||
import io.metersphere.dto.ResultDTO;
|
||||
import io.metersphere.i18n.Translator;
|
||||
import io.metersphere.notice.sender.NoticeModel;
|
||||
import io.metersphere.notice.service.NoticeSendService;
|
||||
import io.metersphere.service.SystemParameterService;
|
||||
|
@ -26,16 +24,14 @@ import io.metersphere.track.service.TestPlanScenarioCaseService;
|
|||
import io.metersphere.track.service.TestPlanTestCaseService;
|
||||
import org.apache.commons.beanutils.BeanMap;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.collections4.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class TestResultService {
|
||||
@Resource
|
||||
private ApiDefinitionExecResultService apiDefinitionExecResultService;
|
||||
|
@ -59,6 +55,14 @@ public class TestResultService {
|
|||
private ApiEnvironmentRunningParamService apiEnvironmentRunningParamService;
|
||||
@Resource
|
||||
private RedisTemplateService redisTemplateService;
|
||||
@Resource
|
||||
private NoticeSendService noticeSendService;
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private ApiTestCaseMapper apiTestCaseMapper;
|
||||
|
||||
// 场景
|
||||
private static final List<String> scenarioRunModes = new ArrayList<>() {{
|
||||
|
@ -93,6 +97,48 @@ public class TestResultService {
|
|||
|
||||
}};
|
||||
|
||||
private void sendNotice(ApiDefinitionExecResult result, User user) {
|
||||
try {
|
||||
String resourceId = result.getResourceId();
|
||||
ApiTestCaseWithBLOBs apiTestCaseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(resourceId);
|
||||
// 接口定义直接执行不发通知
|
||||
if (apiTestCaseWithBLOBs == null) {
|
||||
return;
|
||||
}
|
||||
BeanMap beanMap = new BeanMap(apiTestCaseWithBLOBs);
|
||||
|
||||
String event;
|
||||
String status;
|
||||
if (StringUtils.equals(result.getStatus(), "success")) {
|
||||
event = NoticeConstants.Event.EXECUTE_SUCCESSFUL;
|
||||
status = "成功";
|
||||
} else {
|
||||
event = NoticeConstants.Event.EXECUTE_FAILED;
|
||||
status = "失败";
|
||||
}
|
||||
if (user == null && StringUtils.isNotBlank(result.getUserId())) {
|
||||
user = userMapper.selectByPrimaryKey(result.getUserId());
|
||||
}
|
||||
Map paramMap = new HashMap<>(beanMap);
|
||||
paramMap.put("operator", user != null ? user.getName() : result.getUserId());
|
||||
paramMap.put("status", result.getStatus());
|
||||
String context = "${operator}执行接口用例" + status + ": ${name}";
|
||||
NoticeModel noticeModel = NoticeModel.builder()
|
||||
.operator(result.getUserId() != null ? result.getUserId() : SessionUtils.getUserId())
|
||||
.context(context)
|
||||
.subject("接口用例通知")
|
||||
.paramMap(paramMap)
|
||||
.event(event)
|
||||
.build();
|
||||
|
||||
String taskType = NoticeConstants.TaskType.API_DEFINITION_TASK;
|
||||
Project project = projectMapper.selectByPrimaryKey(apiTestCaseWithBLOBs.getProjectId());
|
||||
noticeSendService.send(project, taskType, noticeModel);
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("消息发送失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行结果存储
|
||||
*
|
||||
|
@ -114,7 +160,8 @@ public class TestResultService {
|
|||
apiDefinitionExecResultService.saveApiResultByScheduleTask(dto);
|
||||
} else if (caseRunModes.contains(dto.getRunMode())) {
|
||||
// 手动触发/批量触发 用例结果处理
|
||||
apiDefinitionExecResultService.saveApiResult(dto);
|
||||
List<ApiDefinitionExecResult> results = apiDefinitionExecResultService.saveApiResult(dto);
|
||||
sendMessage(results, dto);
|
||||
} else if (scenarioRunModes.contains(dto.getRunMode())) {
|
||||
// 场景报告结果处理
|
||||
apiScenarioReportService.saveResult(dto);
|
||||
|
@ -125,6 +172,23 @@ public class TestResultService {
|
|||
updateTestCaseStates(dto.getRequestResults(), dto.getRunMode());
|
||||
}
|
||||
|
||||
private void sendMessage(List<ApiDefinitionExecResult> results, ResultDTO dto) {
|
||||
results.forEach(result -> {
|
||||
User user = null;
|
||||
if (MapUtils.isNotEmpty(dto.getExtendedParameters())) {
|
||||
if (dto.getExtendedParameters().containsKey("userId") && dto.getExtendedParameters().containsKey("userName")) {
|
||||
user = new User() {{
|
||||
this.setId(dto.getExtendedParameters().get("userId").toString());
|
||||
this.setName(dto.getExtendedParameters().get("userName").toString());
|
||||
}};
|
||||
} else if (dto.getExtendedParameters().containsKey("userId")) {
|
||||
result.setUserId(dto.getExtendedParameters().get("userId").toString());
|
||||
}
|
||||
}
|
||||
sendNotice(result, user);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量存储执行结果
|
||||
*
|
||||
|
@ -134,8 +198,7 @@ public class TestResultService {
|
|||
// 处理环境
|
||||
List<String> environmentList = new LinkedList<>();
|
||||
for (String key : resultDtoMap.keySet()) {
|
||||
List<ResultDTO> dtos = resultDtoMap.get(key);
|
||||
for (ResultDTO dto : dtos) {
|
||||
for (ResultDTO dto : resultDtoMap.get(key)) {
|
||||
if (dto.getArbitraryData() != null && dto.getArbitraryData().containsKey("ENV")) {
|
||||
environmentList = (List<String>) dto.getArbitraryData().get("ENV");
|
||||
}
|
||||
|
@ -148,11 +211,17 @@ public class TestResultService {
|
|||
}
|
||||
//测试计划定时任务-接口执行逻辑的话,需要同步测试计划的报告数据
|
||||
if (StringUtils.equals(key, "schedule-task")) {
|
||||
apiDefinitionExecResultService.batchSaveApiResult(dtos, true);
|
||||
Map<ResultDTO, List<ApiDefinitionExecResult>> results = apiDefinitionExecResultService.batchSaveApiResult(resultDtoMap.get(key), true);
|
||||
for (ResultDTO dto : results.keySet()) {
|
||||
sendMessage(results.get(dto), dto);
|
||||
}
|
||||
} else if (StringUtils.equals(key, "api-test-case-task")) {
|
||||
apiDefinitionExecResultService.batchSaveApiResult(dtos, false);
|
||||
Map<ResultDTO, List<ApiDefinitionExecResult>> results = apiDefinitionExecResultService.batchSaveApiResult(resultDtoMap.get(key), false);
|
||||
for (ResultDTO dto : results.keySet()) {
|
||||
sendMessage(results.get(dto), dto);
|
||||
}
|
||||
} else if (StringUtils.equalsAny(key, "api-scenario-task")) {
|
||||
apiScenarioReportService.batchSaveResult(dtos);
|
||||
apiScenarioReportService.batchSaveResult(resultDtoMap.get(key));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue