feat(接口测试): 完善失败重试相关功能
This commit is contained in:
parent
53dc397e51
commit
97e4fca7ff
|
@ -22,10 +22,15 @@ public class RequestResultExpandDTO extends RequestResult {
|
|||
public RequestResultExpandDTO() {
|
||||
}
|
||||
|
||||
public RequestResultExpandDTO(String name, String status) {
|
||||
this.setName(name);
|
||||
this.setStatus(status);
|
||||
}
|
||||
|
||||
public RequestResultExpandDTO(ApiScenarioReportResultWithBLOBs requestResult) {
|
||||
if(requestResult.getBaseInfo() != null){
|
||||
if (requestResult.getBaseInfo() != null) {
|
||||
try {
|
||||
ApiScenarioReportBaseInfoDTO dto = JSONObject.parseObject(requestResult.getBaseInfo(),ApiScenarioReportBaseInfoDTO.class);
|
||||
ApiScenarioReportBaseInfoDTO dto = JSONObject.parseObject(requestResult.getBaseInfo(), ApiScenarioReportBaseInfoDTO.class);
|
||||
this.setName(dto.getReqName());
|
||||
this.setSuccess(dto.isReqSuccess());
|
||||
this.setError(dto.getReqError());
|
||||
|
@ -39,8 +44,8 @@ public class RequestResultExpandDTO extends RequestResult {
|
|||
responseResult.setResponseCode(dto.getRspCode());
|
||||
responseResult.setResponseTime(dto.getRspTime());
|
||||
this.setResponseResult(responseResult);
|
||||
}catch (Exception e){
|
||||
LogUtil.error("Parse report base-info error :"+ e.getMessage());
|
||||
} catch (Exception e) {
|
||||
LogUtil.error("Parse report base-info error :" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,16 +11,16 @@ import io.metersphere.dto.ResultDTO;
|
|||
import io.metersphere.jmeter.JMeterBase;
|
||||
import io.metersphere.jmeter.MsExecListener;
|
||||
import io.metersphere.utils.LoggerUtil;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import io.metersphere.utils.RetryResultUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class APISingleResultListener implements MsExecListener {
|
||||
private ApiExecutionQueueService apiExecutionQueueService;
|
||||
private final static String RETRY = "MsRetry_";
|
||||
private List<SampleResult> queues;
|
||||
|
||||
/**
|
||||
|
@ -35,11 +35,8 @@ public class APISingleResultListener implements MsExecListener {
|
|||
@Override
|
||||
public void handleTeardownTest(List<SampleResult> results, ResultDTO dto, Map<String, Object> kafkaConfig) {
|
||||
LoggerUtil.info("接收到执行结果开始处理报告【" + dto.getReportId() + " 】,资源【 " + dto.getTestId() + " 】");
|
||||
// 暂时保留
|
||||
// dto.setConsole(FixedCapacityUtils.getJmeterLogger(dto.getReportId()));
|
||||
// JMeterBase.resultFormatting(results, dto);
|
||||
// CommonBeanFactory.getBean(TestResultService.class).saveResults(dto);
|
||||
this.clearLoops(results);
|
||||
// 清理过程步骤
|
||||
results = RetryResultUtil.clearLoops(results);
|
||||
queues.addAll(results);
|
||||
}
|
||||
|
||||
|
@ -47,22 +44,20 @@ public class APISingleResultListener implements MsExecListener {
|
|||
public void testEnded(ResultDTO dto, Map<String, Object> kafkaConfig) {
|
||||
try {
|
||||
if (dto.isRetryEnable()) {
|
||||
LoggerUtil.info("进入TEST-END处理报告【" + dto.getReportId() + " 】,进入重试结果处理");
|
||||
mergeRetryResults(queues);
|
||||
LoggerUtil.info("重试结果处理【" + dto.getReportId() + " 】开始");
|
||||
RetryResultUtil.mergeRetryResults(queues);
|
||||
LoggerUtil.info("重试结果处理【" + dto.getReportId() + " 】结束");
|
||||
}
|
||||
|
||||
JMeterBase.resultFormatting(queues, dto);
|
||||
|
||||
dto.setConsole(FixedCapacityUtils.getJmeterLogger(dto.getReportId(), !StringUtils.equals(dto.getReportType(), RunModeConstants.SET_REPORT.toString())));
|
||||
// 入库存储
|
||||
CommonBeanFactory.getBean(TestResultService.class).saveResults(dto);
|
||||
|
||||
LoggerUtil.info("进入TEST-END处理报告【" + dto.getReportId() + " 】" + dto.getRunMode() + " 整体执行完成");
|
||||
// 全局并发队列
|
||||
PoolExecBlockingQueueUtil.offer(dto.getReportId());
|
||||
// 整体执行结束更新资源状态
|
||||
CommonBeanFactory.getBean(TestResultService.class).testEnded(dto);
|
||||
|
||||
if (apiExecutionQueueService == null) {
|
||||
apiExecutionQueueService = CommonBeanFactory.getBean(ApiExecutionQueueService.class);
|
||||
}
|
||||
|
@ -83,43 +78,4 @@ public class APISingleResultListener implements MsExecListener {
|
|||
queues.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并掉重试结果;保留最后一次重试结果
|
||||
*
|
||||
* @param results
|
||||
*/
|
||||
public void mergeRetryResults(List<SampleResult> results) {
|
||||
if (CollectionUtils.isNotEmpty(results)) {
|
||||
Map<String, List<SampleResult>> resultMap = results.stream().collect(Collectors.groupingBy(SampleResult::getResourceId));
|
||||
List<SampleResult> list = new LinkedList<>();
|
||||
resultMap.forEach((k, v) -> {
|
||||
// 校验是否含重试结果
|
||||
List<SampleResult> isRetryResults = v
|
||||
.stream()
|
||||
.filter(c -> StringUtils.isNotEmpty(c.getSampleLabel()) && c.getSampleLabel().startsWith(RETRY))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(isRetryResults) && v.size() > 1) {
|
||||
Collections.sort(v, Comparator.comparing(SampleResult::getResourceId));
|
||||
SampleResult sampleResult = v.get(v.size() - 1);
|
||||
sampleResult.setSampleLabel(v.get(0).getSampleLabel());
|
||||
list.add(sampleResult);
|
||||
} else {
|
||||
list.addAll(v);
|
||||
}
|
||||
});
|
||||
results.clear();
|
||||
results.addAll(list);
|
||||
}
|
||||
}
|
||||
|
||||
private void clearLoops(List<SampleResult> results) {
|
||||
if (org.apache.commons.collections.CollectionUtils.isNotEmpty(results)) {
|
||||
results = results.stream().filter(sampleResult ->
|
||||
StringUtils.isNotEmpty(sampleResult.getSampleLabel())
|
||||
&& !sampleResult.getSampleLabel().startsWith("MS_CLEAR_LOOPS_VAR_"))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ 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.dto.RequestResult;
|
||||
import io.metersphere.dto.ResultDTO;
|
||||
import io.metersphere.notice.sender.NoticeModel;
|
||||
|
@ -499,21 +498,6 @@ public class ApiDefinitionExecResultService {
|
|||
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"));
|
||||
List<ApiDefinitionExecResultExpand> list = extApiDefinitionExecResultMapper.list(request);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package io.metersphere.api.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.parser.Feature;
|
||||
import io.metersphere.api.dto.*;
|
||||
|
@ -36,8 +35,6 @@ 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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -52,7 +49,6 @@ import java.util.stream.Collectors;
|
|||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class ApiScenarioReportService {
|
||||
Logger testPlanLog = LoggerFactory.getLogger("testPlanExecuteLog");
|
||||
@Resource
|
||||
private ExtApiScenarioReportMapper extApiScenarioReportMapper;
|
||||
@Resource
|
||||
|
@ -116,14 +112,6 @@ public class ApiScenarioReportService {
|
|||
example.createCriteria().andReportIdEqualTo(dto.getReportId());
|
||||
List<ApiScenarioReportResult> requestResults = apiScenarioReportResultMapper.selectByExample(example);
|
||||
|
||||
if (StringUtils.isNotEmpty(dto.getTestPlanReportId())) {
|
||||
String status = getStatus(requestResults, dto);
|
||||
Map<String, String> reportMap = new HashMap<String, String>() {{
|
||||
this.put(dto.getReportId(), status);
|
||||
}};
|
||||
testPlanLog.info("TestPlanReportId" + JSONArray.toJSONString(dto.getReportId()) + " EXECUTE OVER. SCENARIO STATUS : " + JSONObject.toJSONString(reportMap));
|
||||
}
|
||||
|
||||
ApiScenarioReport scenarioReport;
|
||||
if (StringUtils.equals(dto.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
|
||||
scenarioReport = updatePlanCase(requestResults, dto);
|
||||
|
@ -139,16 +127,6 @@ public class ApiScenarioReportService {
|
|||
}
|
||||
|
||||
public APIScenarioReportResult get(String reportId, boolean selectReportContent) {
|
||||
ApiDefinitionExecResult result = definitionExecResultMapper.selectByPrimaryKey(reportId);
|
||||
if (result != null) {
|
||||
APIScenarioReportResult reportResult = new APIScenarioReportResult();
|
||||
BeanUtils.copyBean(reportResult, result);
|
||||
reportResult.setReportVersion(2);
|
||||
reportResult.setTestId(reportId);
|
||||
ApiScenarioReportDTO dto = apiScenarioReportStructureService.apiIntegratedReport(reportId);
|
||||
reportResult.setContent(JSON.toJSONString(dto));
|
||||
return reportResult;
|
||||
}
|
||||
APIScenarioReportResult reportResult = extApiScenarioReportMapper.get(reportId);
|
||||
if (reportResult != null) {
|
||||
if (reportResult.getReportVersion() != null && reportResult.getReportVersion() > 1) {
|
||||
|
@ -159,8 +137,31 @@ public class ApiScenarioReportService {
|
|||
reportResult.setContent(new String(detail.getContent(), StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
return reportResult;
|
||||
}
|
||||
return reportResult;
|
||||
// case 集成报告
|
||||
APIScenarioReportResult result = this.getApiIntegrated(reportId);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* CASE集成报告
|
||||
*
|
||||
* @param reportId
|
||||
* @return
|
||||
*/
|
||||
public APIScenarioReportResult getApiIntegrated(String reportId) {
|
||||
ApiDefinitionExecResult result = definitionExecResultMapper.selectByPrimaryKey(reportId);
|
||||
if (result != null) {
|
||||
APIScenarioReportResult reportResult = new APIScenarioReportResult();
|
||||
BeanUtils.copyBean(reportResult, result);
|
||||
reportResult.setReportVersion(2);
|
||||
reportResult.setTestId(reportId);
|
||||
ApiScenarioReportDTO dto = apiScenarioReportStructureService.apiIntegratedReport(reportId);
|
||||
reportResult.setContent(JSON.toJSONString(dto));
|
||||
return reportResult;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<APIScenarioReportResult> list(QueryAPIReportRequest request) {
|
||||
|
@ -178,12 +179,12 @@ public class ApiScenarioReportService {
|
|||
return list;
|
||||
}
|
||||
|
||||
public QueryAPIReportRequest initRequest(QueryAPIReportRequest request){
|
||||
if(request != null){
|
||||
public QueryAPIReportRequest initRequest(QueryAPIReportRequest request) {
|
||||
if (request != null) {
|
||||
//初始化triggerMode的查询条件: 如果查询API的话,增加 JENKINS_RUN_TEST_PLAN(jenkins调用测试计划时执行的场景) 查询条件
|
||||
if(MapUtils.isNotEmpty(request.getFilters()) && request.getFilters().containsKey("trigger_mode")
|
||||
if (MapUtils.isNotEmpty(request.getFilters()) && request.getFilters().containsKey("trigger_mode")
|
||||
&& CollectionUtils.isNotEmpty(request.getFilters().get("trigger_mode"))
|
||||
&& request.getFilters().get("trigger_mode").contains("API") && !request.getFilters().get("trigger_mode").contains(ReportTriggerMode.JENKINS_RUN_TEST_PLAN.name())){
|
||||
&& request.getFilters().get("trigger_mode").contains("API") && !request.getFilters().get("trigger_mode").contains(ReportTriggerMode.JENKINS_RUN_TEST_PLAN.name())) {
|
||||
request.getFilters().get("trigger_mode").add(ReportTriggerMode.JENKINS_RUN_TEST_PLAN.name());
|
||||
}
|
||||
}
|
||||
|
@ -251,8 +252,8 @@ public class ApiScenarioReportService {
|
|||
report.setTriggerMode(TriggerMode.MANUAL.name());
|
||||
}
|
||||
// UI 调试类型报告不记录更新状态
|
||||
if(report.getExecuteType().equals(ExecuteType.Debug.name()) &&
|
||||
report.getReportType().equals(ReportTypeConstants.UI_INDEPENDENT.name())){
|
||||
if (report.getExecuteType().equals(ExecuteType.Debug.name()) &&
|
||||
report.getReportType().equals(ReportTypeConstants.UI_INDEPENDENT.name())) {
|
||||
return report;
|
||||
}
|
||||
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
|
||||
|
@ -378,7 +379,7 @@ public class ApiScenarioReportService {
|
|||
if (CollectionUtils.isEmpty(reportStatus)) {
|
||||
//查不到任何结果,按照未执行来处理
|
||||
hasUnExecute = true;
|
||||
}else {
|
||||
} else {
|
||||
for (String status : reportStatus) {
|
||||
if (StringUtils.equalsIgnoreCase(status, ExecuteResult.SCENARIO_ERROR.toString())) {
|
||||
hasError = true;
|
||||
|
@ -407,15 +408,13 @@ public class ApiScenarioReportService {
|
|||
|
||||
public void margeReport(String reportId, String runMode, String console) {
|
||||
// 更新场景状态
|
||||
List<String> statusList = null;
|
||||
if (StringUtils.equalsIgnoreCase(runMode, ApiRunMode.DEFINITION.name())) {
|
||||
ApiDefinitionExecResultWithBLOBs result = definitionExecResultMapper.selectByPrimaryKey(reportId);
|
||||
if (!StringUtils.equalsAnyIgnoreCase(result.getStatus(), APITestStatus.Rerunning.name())) {
|
||||
result.setEndTime(System.currentTimeMillis());
|
||||
}
|
||||
statusList = extApiDefinitionExecResultMapper.selectDistinctStatusByReportId(reportId);
|
||||
List<String> statusList = extApiDefinitionExecResultMapper.selectDistinctStatusByReportId(reportId);
|
||||
result.setStatus(this.getIntegrationReportStatus(statusList));
|
||||
result.setEndTime(System.currentTimeMillis());
|
||||
definitionExecResultMapper.updateByPrimaryKeySelective(result);
|
||||
} else {
|
||||
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(reportId);
|
||||
|
@ -423,9 +422,8 @@ public class ApiScenarioReportService {
|
|||
if (!StringUtils.equalsAnyIgnoreCase(report.getStatus(), APITestStatus.Rerunning.name())) {
|
||||
report.setEndTime(System.currentTimeMillis());
|
||||
}
|
||||
statusList = extApiScenarioReportResultMapper.selectDistinctStatusByReportId(reportId);
|
||||
List<String> statusList = extApiScenarioReportResultMapper.selectDistinctStatusByReportId(reportId);
|
||||
report.setStatus(this.getIntegrationReportStatus(statusList));
|
||||
report.setEndTime(System.currentTimeMillis());
|
||||
// 更新报告
|
||||
apiScenarioReportMapper.updateByPrimaryKey(report);
|
||||
}
|
||||
|
@ -509,8 +507,8 @@ public class ApiScenarioReportService {
|
|||
}
|
||||
scenario.setExecuteTimes(executeTimes + 1);
|
||||
// 针对 UI 调试类型的不需要更新
|
||||
if(report.getExecuteType().equals(ExecuteType.Debug.name()) &&
|
||||
report.getReportType().equals(ReportTypeConstants.UI_INDEPENDENT.name())){
|
||||
if (report.getExecuteType().equals(ExecuteType.Debug.name()) &&
|
||||
report.getReportType().equals(ReportTypeConstants.UI_INDEPENDENT.name())) {
|
||||
return report;
|
||||
}
|
||||
uiScenarioMapper.updateByPrimaryKey(scenario);
|
||||
|
|
|
@ -215,11 +215,11 @@ public class ApiScenarioReportStructureService {
|
|||
AtomicLong totalScenario, AtomicLong scenarioError, AtomicLong errorReport, AtomicLong unExecute) {
|
||||
for (StepTreeDTO step : dtoList) {
|
||||
totalScenario.set(totalScenario.longValue() + 1);
|
||||
if (StringUtils.equalsIgnoreCase(step.getTotalStatus(), "fail")) {
|
||||
if (StringUtils.equalsIgnoreCase(step.getTotalStatus(), ExecuteResult.FAIL.getValue())) {
|
||||
scenarioError.set(scenarioError.longValue() + 1);
|
||||
} else if (StringUtils.equalsAnyIgnoreCase(step.getTotalStatus(), "errorCode", ExecuteResult.ERROR_REPORT_RESULT.toString())) {
|
||||
errorReport.set(errorReport.longValue() + 1);
|
||||
} else if (!StringUtils.equalsIgnoreCase(step.getTotalStatus(), "success")) {
|
||||
} else if (!StringUtils.equalsIgnoreCase(step.getTotalStatus(), ExecuteResult.API_SUCCESS.getValue())) {
|
||||
unExecute.set(unExecute.longValue() + 1);
|
||||
}
|
||||
}
|
||||
|
@ -249,11 +249,11 @@ public class ApiScenarioReportStructureService {
|
|||
if (CollectionUtils.isNotEmpty(root.getChildren())) {
|
||||
stepTotal.set((stepTotal.longValue() + root.getChildren().size()));
|
||||
for (StepTreeDTO step : root.getChildren()) {
|
||||
if (StringUtils.equalsAnyIgnoreCase(step.getTotalStatus(), "fail", "error")) {
|
||||
if (StringUtils.equalsAnyIgnoreCase(step.getTotalStatus(), ExecuteResult.FAIL.getValue(), "error")) {
|
||||
stepError.set(stepError.longValue() + 1);
|
||||
} else if (StringUtils.equalsAnyIgnoreCase(step.getTotalStatus(), "errorCode", "errorReportResult")) {
|
||||
stepErrorCode.set(stepErrorCode.longValue() + 1);
|
||||
} else if (!StringUtils.equalsIgnoreCase(step.getTotalStatus(), "success")) {
|
||||
} else if (!StringUtils.equalsIgnoreCase(step.getTotalStatus(), ExecuteResult.API_SUCCESS.getValue())) {
|
||||
stepUnExecute.set(stepUnExecute.longValue() + 1);
|
||||
unExecSize++;
|
||||
}
|
||||
|
@ -263,78 +263,44 @@ public class ApiScenarioReportStructureService {
|
|||
}
|
||||
}
|
||||
|
||||
public void reportFormatting(List<StepTreeDTO> dtoList, Map<String, List<ApiScenarioReportResultWithBLOBs>> maps, boolean isLoops) {
|
||||
public void reportFormatting(List<StepTreeDTO> dtoList, Map<String, List<ApiScenarioReportResultWithBLOBs>> maps) {
|
||||
// 按照创建时间排序
|
||||
for (int index = 0; index < dtoList.size(); index++) {
|
||||
StepTreeDTO dto = dtoList.get(index);
|
||||
dto.setIndex((index + 1));
|
||||
List<ApiScenarioReportResultWithBLOBs> reportResults = maps.get(dto.getResourceId());
|
||||
if (CollectionUtils.isNotEmpty(reportResults)) {
|
||||
if (reportResults.size() > 1) {
|
||||
for (int i = 0; i < reportResults.size(); i++) {
|
||||
ApiScenarioReportResultWithBLOBs reportResult = reportResults.get(i);
|
||||
//来自报告导出的数据
|
||||
if (i == 0) {
|
||||
if (reportResult.getContent() != null) {
|
||||
dto.setValue(JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class));
|
||||
dto.setErrorCode(reportResults.get(0).getErrorCode());
|
||||
} else {
|
||||
RequestResultExpandDTO requestResultExpandDTO = new RequestResultExpandDTO(reportResult);
|
||||
dto.setStepId(reportResults.get(i).getId());
|
||||
dto.setValue(requestResultExpandDTO);
|
||||
dto.setErrorCode(reportResults.get(0).getErrorCode());
|
||||
}
|
||||
} else {
|
||||
if (reportResult.getContent() != null) {
|
||||
StepTreeDTO step = new StepTreeDTO(dto.getLabel(), UUID.randomUUID().toString(), dto.getType(), reportResults.get(i).getId(), (i + 1));
|
||||
step.setValue(JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class));
|
||||
step.setErrorCode(reportResults.get(i).getErrorCode());
|
||||
dtoList.add(step);
|
||||
} else {
|
||||
StepTreeDTO step = new StepTreeDTO(dto.getLabel(), UUID.randomUUID().toString(), dto.getType(), reportResults.get(i).getId(), (i + 1));
|
||||
RequestResultExpandDTO requestResultExpandDTO = new RequestResultExpandDTO(reportResult);
|
||||
step.setValue(requestResultExpandDTO);
|
||||
step.setErrorCode(reportResults.get(i).getErrorCode());
|
||||
dtoList.add(step);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ApiScenarioReportResultWithBLOBs reportResult = reportResults.get(0);
|
||||
for (int i = 0; i < reportResults.size(); i++) {
|
||||
ApiScenarioReportResultWithBLOBs reportResult = reportResults.get(i);
|
||||
StepTreeDTO step = i == 0 ? dto :
|
||||
new StepTreeDTO(dto.getLabel(), UUID.randomUUID().toString(), dto.getType(), reportResults.get(i).getId(), (i + 1));
|
||||
step.setStepId(reportResults.get(i).getId());
|
||||
RequestResult result = new RequestResultExpandDTO(reportResult);
|
||||
if (reportResult.getContent() != null) {
|
||||
String content = new String(reportResults.get(0).getContent(), StandardCharsets.UTF_8);
|
||||
dto.setValue(JSON.parseObject(content, RequestResult.class));
|
||||
dto.setErrorCode(reportResults.get(0).getErrorCode());
|
||||
} else {
|
||||
RequestResultExpandDTO requestResultExpandDTO = new RequestResultExpandDTO(reportResult);
|
||||
dto.setStepId(reportResults.get(0).getId());
|
||||
dto.setValue(requestResultExpandDTO);
|
||||
dto.setErrorCode(reportResults.get(0).getErrorCode());
|
||||
dto.setTotalStatus(requestResultExpandDTO.getStatus());
|
||||
result = JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class);
|
||||
}
|
||||
step.setValue(result);
|
||||
step.setErrorCode(reportResults.get(i).getErrorCode());
|
||||
if (i > 0) {
|
||||
dtoList.add(step);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 未执行请求
|
||||
if (StringUtils.isNotEmpty(dto.getType()) && requests.contains(dto.getType()) && dto.getValue() == null || isUiUnExecuteCommand(dto)) {
|
||||
RequestResultExpandDTO requestResultExpandDTO = new RequestResultExpandDTO();
|
||||
requestResultExpandDTO.setStatus("unexecute");
|
||||
requestResultExpandDTO.setName(dto.getLabel());
|
||||
dto.setTotalStatus("unexecute");
|
||||
dto.setValue(requestResultExpandDTO);
|
||||
dto.setTotalStatus(ExecuteResult.UN_EXECUTE.getValue());
|
||||
dto.setValue(new RequestResultExpandDTO(dto.getLabel(), ExecuteResult.UN_EXECUTE.getValue()));
|
||||
} else if (StringUtils.isNotEmpty(dto.getType()) && controls.contains(dto.getType()) && dto.getValue() == null) {
|
||||
RequestResultExpandDTO requestResultExpandDTO = new RequestResultExpandDTO();
|
||||
requestResultExpandDTO.setStatus("success");
|
||||
requestResultExpandDTO.setName(dto.getLabel());
|
||||
dto.setTotalStatus("success");
|
||||
dto.setValue(requestResultExpandDTO);
|
||||
} else {
|
||||
if (dto.getValue() instanceof RequestResultExpandDTO && StringUtils.isNotEmpty(((RequestResultExpandDTO) dto.getValue()).getStatus())) {
|
||||
dto.setTotalStatus(((RequestResultExpandDTO) dto.getValue()).getStatus());
|
||||
} else if (dto.getValue() != null) {
|
||||
if (dto.getValue().getError() > 0 || BooleanUtils.isNotTrue(dto.getValue().isSuccess())) {
|
||||
dto.setTotalStatus("fail");
|
||||
} else {
|
||||
dto.setTotalStatus("success");
|
||||
}
|
||||
// 条件控制步骤
|
||||
dto.setTotalStatus(ExecuteResult.API_SUCCESS.getValue());
|
||||
dto.setValue(new RequestResultExpandDTO(dto.getLabel(), ExecuteResult.API_SUCCESS.getValue()));
|
||||
} else if (dto.getValue() instanceof RequestResultExpandDTO && StringUtils.isNotEmpty(((RequestResultExpandDTO) dto.getValue()).getStatus())) {
|
||||
dto.setTotalStatus(((RequestResultExpandDTO) dto.getValue()).getStatus());
|
||||
} else if (dto.getValue() != null) {
|
||||
if (dto.getValue().getError() > 0 || BooleanUtils.isNotTrue(dto.getValue().isSuccess())) {
|
||||
dto.setTotalStatus(ExecuteResult.FAIL.getValue());
|
||||
} else {
|
||||
dto.setTotalStatus(ExecuteResult.API_SUCCESS.getValue());
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotEmpty(dto.getErrorCode()) && StringUtils.isEmpty(dto.getTotalStatus())) {
|
||||
|
@ -342,7 +308,7 @@ public class ApiScenarioReportStructureService {
|
|||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(dto.getChildren())) {
|
||||
reportFormatting(dto.getChildren(), maps, StringUtils.equalsIgnoreCase(dto.getType(), "LoopController"));
|
||||
reportFormatting(dto.getChildren(), maps);
|
||||
|
||||
if (StringUtils.isEmpty(dto.getErrorCode())) {
|
||||
//统计child的errorCode,合并到parent中
|
||||
|
@ -361,9 +327,9 @@ public class ApiScenarioReportStructureService {
|
|||
int errorReportCount = 0;
|
||||
int successCount = 0;
|
||||
for (StepTreeDTO child : dto.getChildren()) {
|
||||
if (StringUtils.equalsIgnoreCase(child.getTotalStatus(), "fail")) {
|
||||
if (StringUtils.equalsIgnoreCase(child.getTotalStatus(), ExecuteResult.FAIL.getValue())) {
|
||||
failCount++;
|
||||
} else if (StringUtils.equalsIgnoreCase(child.getTotalStatus(), "success")) {
|
||||
} else if (StringUtils.equalsIgnoreCase(child.getTotalStatus(), ExecuteResult.API_SUCCESS.getValue())) {
|
||||
successCount++;
|
||||
} else if (StringUtils.equalsAnyIgnoreCase(child.getTotalStatus(), "errorCode", "errorReportResult")) {
|
||||
errorReportCount++;
|
||||
|
@ -374,23 +340,23 @@ public class ApiScenarioReportStructureService {
|
|||
if (failCount == 0 && errorReportCount == 0 && successCount == 0) {
|
||||
dto.setTotalStatus(ExecuteResult.UN_EXECUTE.toString());
|
||||
} else if (successCount == dto.getChildren().size() || (successCount > 0 && errorReportCount == 0 && failCount == 0)) {
|
||||
dto.setTotalStatus("success");
|
||||
dto.setTotalStatus(ExecuteResult.API_SUCCESS.getValue());
|
||||
} else {
|
||||
if (StringUtils.equalsIgnoreCase(dto.getType(), "scenario")) {
|
||||
if (failCount > 0) {
|
||||
dto.setTotalStatus("fail");
|
||||
dto.setTotalStatus(ExecuteResult.FAIL.getValue());
|
||||
} else if (errorReportCount > 0) {
|
||||
dto.setTotalStatus("errorCode");
|
||||
} else {
|
||||
dto.setTotalStatus("success");
|
||||
dto.setTotalStatus(ExecuteResult.API_SUCCESS.getValue());
|
||||
}
|
||||
} else {
|
||||
if (failCount > 0) {
|
||||
dto.setTotalStatus("fail");
|
||||
dto.setTotalStatus(ExecuteResult.FAIL.getValue());
|
||||
} else if (errorReportCount > 0) {
|
||||
dto.setTotalStatus("errorCode");
|
||||
} else {
|
||||
dto.setTotalStatus("success");
|
||||
dto.setTotalStatus(ExecuteResult.API_SUCCESS.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -398,12 +364,10 @@ public class ApiScenarioReportStructureService {
|
|||
if (StringUtils.isEmpty(dto.getTotalStatus())) {
|
||||
dto.setTotalStatus(ExecuteResult.UN_EXECUTE.toString());
|
||||
} else if (StringUtils.equalsAnyIgnoreCase(dto.getTotalStatus(), "error")) {
|
||||
dto.setTotalStatus("fail");
|
||||
dto.setTotalStatus(ExecuteResult.FAIL.getValue());
|
||||
}
|
||||
}
|
||||
if (isLoops) {
|
||||
this.orderLoops(dtoList);
|
||||
}
|
||||
this.orderLoops(dtoList);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -411,7 +375,7 @@ public class ApiScenarioReportStructureService {
|
|||
*/
|
||||
private void orderLoops(List<StepTreeDTO> dtoList) {
|
||||
try {
|
||||
List<StepTreeDTO> steps = dtoList.stream().filter(e -> e.getValue() == null || StringUtils.isEmpty(e.getValue().getId()))
|
||||
List<StepTreeDTO> steps = dtoList.stream().filter(e -> e.getValue() == null || e.getValue().getStartTime() == 0)
|
||||
.collect(Collectors.toList());
|
||||
// 都是没有结果的步骤,不需要再次排序
|
||||
if (dtoList.size() == steps.size()) {
|
||||
|
@ -503,9 +467,9 @@ public class ApiScenarioReportStructureService {
|
|||
treeDTO.setTotalStatus(expandDTO.getStatus());
|
||||
} else {
|
||||
if (expandDTO.isSuccess()) {
|
||||
treeDTO.setTotalStatus("success");
|
||||
treeDTO.setTotalStatus(ExecuteResult.API_SUCCESS.getValue());
|
||||
} else {
|
||||
treeDTO.setTotalStatus("fail");
|
||||
treeDTO.setTotalStatus(ExecuteResult.FAIL.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -613,7 +577,7 @@ public class ApiScenarioReportStructureService {
|
|||
|
||||
// 匹配结果
|
||||
Map<String, List<ApiScenarioReportResultWithBLOBs>> maps = reportResults.stream().collect(Collectors.groupingBy(ApiScenarioReportResult::getResourceId));
|
||||
this.reportFormatting(stepList, maps, false);
|
||||
this.reportFormatting(stepList, maps);
|
||||
|
||||
reportDTO = this.countReportNum(stepList, reportDTO);
|
||||
// 统计场景数据
|
||||
|
@ -637,7 +601,7 @@ public class ApiScenarioReportStructureService {
|
|||
|
||||
//统计未执行的请求数量
|
||||
AtomicLong allUnExecute = new AtomicLong();
|
||||
this.countAllUnexecute(stepList, allUnExecute);
|
||||
this.countAllUnexpected(stepList, allUnExecute);
|
||||
reportDTO.setUnExecute(allUnExecute.longValue());
|
||||
//之前的total中请求数是按照获得报告的响应数来算的。这里要加上未执行的数量
|
||||
reportDTO.setTotal(reportDTO.getTotal() + allUnExecute.longValue());
|
||||
|
@ -688,7 +652,7 @@ public class ApiScenarioReportStructureService {
|
|||
}
|
||||
}
|
||||
|
||||
private void countAllUnexecute(List<StepTreeDTO> stepList, AtomicLong allUnExecute) {
|
||||
private void countAllUnexpected(List<StepTreeDTO> stepList, AtomicLong allUnExecute) {
|
||||
for (StepTreeDTO step : stepList) {
|
||||
if (step.getValue() != null) {
|
||||
if (step.getValue() instanceof RequestResultExpandDTO
|
||||
|
@ -697,7 +661,7 @@ public class ApiScenarioReportStructureService {
|
|||
}
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(step.getChildren())) {
|
||||
this.countAllUnexecute(step.getChildren(), allUnExecute);
|
||||
this.countAllUnexpected(step.getChildren(), allUnExecute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,10 @@ public enum ExecuteResult {
|
|||
//场景执行状态(兼容旧数据)
|
||||
SCENARIO_SUCCESS("Success"), SCENARIO_ERROR("Error"),
|
||||
//测试计划执行状态(兼容旧数据)
|
||||
TEST_PLAN_PREPARE("PREPARE"), TEST_PLAN_RUNNING("RUNNING");
|
||||
TEST_PLAN_PREPARE("PREPARE"), TEST_PLAN_RUNNING("RUNNING"),
|
||||
|
||||
FAIL("fail");
|
||||
|
||||
private String value;
|
||||
|
||||
ExecuteResult(String value) {
|
||||
|
@ -24,4 +27,7 @@ public enum ExecuteResult {
|
|||
return this.value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<span style="margin-left: 10px">{{$t('report.test_end_time')}}:</span>
|
||||
<span class="time"> {{ report.endTime | timestampFormatDate }}</span>
|
||||
</span>
|
||||
<div style="float: right">
|
||||
<el-button v-if="!isPlan && (!debug || exportFlag) && !isTemplate && !isUi" v-permission="['PROJECT_API_REPORT:READ+EXPORT']" :disabled="isReadOnly" class="export-button" plain type="primary" size="mini" @click="handleExport(report.name)" style="margin-right: 10px">
|
||||
{{ $t('test_track.plan_view.export_report') }}
|
||||
</el-button>
|
||||
|
@ -52,7 +53,7 @@
|
|||
<el-button v-if="showCancelButton" class="export-button" plain size="mini" @click="returnView" >
|
||||
{{$t('commons.cancel')}}
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</header>
|
||||
|
@ -136,6 +137,7 @@ export default {
|
|||
this.$error(res.data);
|
||||
}else{
|
||||
this.$success("已经开始重跑,稍后刷新结果查看");
|
||||
this.returnView();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
</template>
|
||||
<api-cases :is-db="isDb" :share-id="shareId" :is-share="isShare" :report="report" :is-template="isTemplate"
|
||||
:plan-id="planId" @setSize="setFailureSize"/>
|
||||
<el-button class="rerun-button" plain size="mini" v-if="showRerunBtn && (failureSize > 0 || unExecuteSize > 0)" @click="rerun">
|
||||
{{$t('api_test.automation.rerun')}}
|
||||
<el-button class="rerun-button" plain size="mini" v-if="showRerunBtn && (failureSize > 0 || unExecuteSize > 0) && isRerun" @click="rerun">
|
||||
{{ $t('api_test.automation.rerun') }}
|
||||
</el-button>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane style="min-height: 500px" name="third" v-if="errorReportEnable">
|
||||
|
@ -20,8 +20,8 @@
|
|||
</template>
|
||||
<api-cases :is-db="isDb" :is-error-report="true" :share-id="shareId" :is-share="isShare" :report="report"
|
||||
:is-template="isTemplate" :plan-id="planId" @setSize="setErrorReportSize"/>
|
||||
<el-button class="rerun-button" plain size="mini" v-if="showRerunBtn && (failureSize > 0 || unExecuteSize > 0)" @click="rerun">
|
||||
{{$t('api_test.automation.rerun')}}
|
||||
<el-button class="rerun-button" plain size="mini" v-if="showRerunBtn && (failureSize > 0 || unExecuteSize > 0) && isRerun" @click="rerun">
|
||||
{{ $t('api_test.automation.rerun') }}
|
||||
</el-button>
|
||||
|
||||
</el-tab-pane>
|
||||
|
@ -32,8 +32,8 @@
|
|||
<api-cases :is-db="isDb" :is-un-execute="true" :share-id="shareId" :is-share="isShare" :report="report"
|
||||
:is-template="isTemplate" :plan-id="planId" @setSize="setUnExecuteSize"/>
|
||||
|
||||
<el-button class="rerun-button" plain size="mini" v-if="showRerunBtn && (failureSize > 0 || unExecuteSize > 0)" @click="rerun">
|
||||
{{$t('api_test.automation.rerun')}}
|
||||
<el-button class="rerun-button" plain size="mini" v-if="showRerunBtn && (failureSize > 0 || unExecuteSize > 0) && isRerun" @click="rerun">
|
||||
{{ $t('api_test.automation.rerun') }}
|
||||
</el-button>
|
||||
</el-tab-pane>
|
||||
|
||||
|
@ -43,8 +43,8 @@
|
|||
</template>
|
||||
<api-cases :is-db="isDb" :is-all="true" :share-id="shareId" :is-share="isShare" :report="report"
|
||||
:is-template="isTemplate" :plan-id="planId" @setSize="setAllSize"/>
|
||||
<el-button class="rerun-button" plain size="mini" v-if="showRerunBtn && (failureSize > 0 || unExecuteSize > 0)" @click="rerun">
|
||||
{{$t('api_test.automation.rerun')}}
|
||||
<el-button class="rerun-button" plain size="mini" v-if="showRerunBtn && (failureSize > 0 || unExecuteSize > 0) && isRerun" @click="rerun">
|
||||
{{ $t('api_test.automation.rerun') }}
|
||||
</el-button>
|
||||
|
||||
</el-tab-pane>
|
||||
|
@ -69,12 +69,12 @@ export default {
|
|||
activeName: 'first',
|
||||
failureSize: 0,
|
||||
errorReportSize: 0,
|
||||
unExecuteSize:0,
|
||||
unExecuteSize: 0,
|
||||
allSize: 0,
|
||||
showRerunBtn: true,
|
||||
};
|
||||
},
|
||||
created(){
|
||||
created() {
|
||||
this.showRerunBtn = hasLicense();
|
||||
},
|
||||
props: [
|
||||
|
@ -101,6 +101,13 @@ export default {
|
|||
let disable = this.report.config && this.report.config.api.children.all.enable === false;
|
||||
return !disable;
|
||||
},
|
||||
isRerun() {
|
||||
return ((this.report && this.report.apiFailureCases)
|
||||
|| (this.report && this.report.unExecuteCases)
|
||||
|| (this.report && this.report.scenarioFailureCases)
|
||||
|| (this.report && this.report.unExecuteScenarios)
|
||||
|| (this.report && this.report.loadFailureCases));
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
resultEnable() {
|
||||
|
@ -137,7 +144,7 @@ export default {
|
|||
setErrorReportSize(size) {
|
||||
this.errorReportSize = size;
|
||||
},
|
||||
setUnExecuteSize(size){
|
||||
setUnExecuteSize(size) {
|
||||
this.unExecuteSize = size;
|
||||
},
|
||||
setAllSize(size) {
|
||||
|
@ -145,7 +152,7 @@ export default {
|
|||
},
|
||||
handleClick(tab, event) {
|
||||
},
|
||||
rerun(){
|
||||
rerun() {
|
||||
let type = "TEST_PLAN";
|
||||
let scenarios = [];
|
||||
let cases = [];
|
||||
|
@ -158,24 +165,23 @@ export default {
|
|||
performanceCases: performanceCases
|
||||
}
|
||||
// 获取需要重跑的用例
|
||||
if(this.report && this.report.apiFailureCases){
|
||||
this.format(cases,this.report.apiFailureCases);
|
||||
if (this.report && this.report.apiFailureCases) {
|
||||
this.format(cases, this.report.apiFailureCases);
|
||||
}
|
||||
if(this.report && this.report.unExecuteCases){
|
||||
this.format(cases,this.report.unExecuteCases);
|
||||
if (this.report && this.report.unExecuteCases) {
|
||||
this.format(cases, this.report.unExecuteCases);
|
||||
}
|
||||
// 获取需要重跑的场景
|
||||
if(this.report && this.report.scenarioFailureCases){
|
||||
this.format(scenarios,this.report.scenarioFailureCases);
|
||||
if (this.report && this.report.scenarioFailureCases) {
|
||||
this.format(scenarios, this.report.scenarioFailureCases);
|
||||
}
|
||||
if(this.report && this.report.unExecuteScenarios){
|
||||
this.format(scenarios,this.report.unExecuteScenarios);
|
||||
if (this.report && this.report.unExecuteScenarios) {
|
||||
this.format(scenarios, this.report.unExecuteScenarios);
|
||||
}
|
||||
// 获取需要重跑的性能用例
|
||||
if(this.report && this.report.loadFailureCases){
|
||||
this.format(performanceCases,this.report.loadFailureCases);
|
||||
if (this.report && this.report.loadFailureCases) {
|
||||
this.format(performanceCases, this.report.loadFailureCases);
|
||||
}
|
||||
|
||||
this.$post('/api/test/exec/rerun', rerunObj, res => {
|
||||
if (res.data !== 'SUCCESS') {
|
||||
this.$error(res.data);
|
||||
|
@ -184,11 +190,11 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
format(cases, datas){
|
||||
if(this.report && datas){
|
||||
datas.forEach(item=>{
|
||||
if(item){
|
||||
let obj = {id: item.id, reportId: item.reportId,userId:item.createUser};
|
||||
format(cases, datas) {
|
||||
if (this.report && datas) {
|
||||
datas.forEach(item => {
|
||||
if (item) {
|
||||
let obj = {id: item.id, reportId: item.reportId, userId: item.createUser};
|
||||
cases.push(obj);
|
||||
}
|
||||
});
|
||||
|
@ -199,13 +205,13 @@ export default {
|
|||
</script>
|
||||
|
||||
<style scoped>
|
||||
.rerun-button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
margin-right: 10px;
|
||||
z-index: 1100;
|
||||
background-color: #F2F9EF;
|
||||
color: #87C45D;
|
||||
}
|
||||
.rerun-button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
margin-right: 10px;
|
||||
z-index: 1100;
|
||||
background-color: #F2F9EF;
|
||||
color: #87C45D;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -2750,7 +2750,7 @@ export default {
|
|||
report_name: "Report name",
|
||||
run_with_resource_pool: "Run Within Resource pool",
|
||||
retry_on_failure: "retry on failure",
|
||||
retry_message: "Retry the interface/UI use case, if it still fails after retries n times, use the failed use case",
|
||||
retry_message: "Retry the interface/UI use case, if it still fails after retries n times, the use case failed",
|
||||
retry: "Retry",
|
||||
retry_frequency: "Frequency"
|
||||
},
|
||||
|
|
|
@ -2758,7 +2758,7 @@ export default {
|
|||
report_name: "报告名称",
|
||||
run_with_resource_pool: "资源池运行",
|
||||
retry_on_failure: "失败重试",
|
||||
retry_message: "重试接口/UI用例,重试n次后,仍然失败,则用失败用例",
|
||||
retry_message: "重试接口/UI用例,重试n次后,仍然失败,则用例失败",
|
||||
retry: "重试",
|
||||
retry_frequency: "次"
|
||||
},
|
||||
|
|
|
@ -2752,7 +2752,7 @@ export default {
|
|||
report_name: "報告名稱",
|
||||
run_with_resource_pool: "資源池運行",
|
||||
retry_on_failure: "失敗重試",
|
||||
retry_message: "重試接口/UI用例,重試n次後,仍然失敗,則用失敗用例",
|
||||
retry_message: "重試接口/UI用例,重試n次後,仍然失敗,則用例失敗",
|
||||
retry: "重試",
|
||||
retry_frequency: "次"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue