feat(误报库): 误报库功能开发

误报库功能开发
This commit is contained in:
song-tianyang 2021-12-31 11:27:21 +08:00 committed by song-tianyang
parent 61bc49d5f6
commit e57822abae
49 changed files with 2715 additions and 460 deletions

View File

@ -13,16 +13,19 @@ public class ApiScenarioReportDTO {
private long totalTime; private long totalTime;
private long total; private long total;
private long error; private long error;
private long errorCode;
private long scenarioTotal; private long scenarioTotal;
private long scenarioError; private long scenarioError;
private long scenarioSuccess; private long scenarioSuccess;
private long scenarioErrorReport;
private long scenarioStepTotal; private long scenarioStepTotal;
private long scenarioStepError; private long scenarioStepError;
private long scenarioStepSuccess; private long scenarioStepSuccess;
private long scenarioStepErrorReport;
private long totalAssertions = 0; private long totalAssertions = 0;
private long passAssertions = 0; private long passAssertions = 0;
private long errorCodeAssertions = 0;
} }

View File

@ -0,0 +1,34 @@
package io.metersphere.api.dto;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
public class ErrorReportLibraryParseDTO {
public List<String> errorCodeList;
public ErrorReportLibraryParseDTO() {
this.errorCodeList = new ArrayList<>();
}
public String getErrorCodeStr(){
if(CollectionUtils.isNotEmpty(this.errorCodeList)){
String errorCodeStr = StringUtils.join(this.errorCodeList,";");
//控制字符串长度
if(errorCodeStr.length() > 10){
return errorCodeStr.substring(0,10)+"...";
}else {
return errorCodeStr;
}
}else {
return "";
}
}
}

View File

@ -15,6 +15,9 @@ public class StepTreeDTO {
private String label; private String label;
private RequestResult value; private RequestResult value;
//误报库编码
private String errorCode;
private List<StepTreeDTO> children; private List<StepTreeDTO> children;
public StepTreeDTO() { public StepTreeDTO() {

View File

@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import io.metersphere.api.dto.definition.parse.JMeterScriptUtil; import io.metersphere.api.dto.definition.parse.JMeterScriptUtil;
import io.metersphere.api.dto.definition.request.ElementUtil; import io.metersphere.api.dto.definition.request.ElementUtil;
import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.ParameterConfig;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
import io.metersphere.api.dto.definition.request.auth.MsAuthManager; import io.metersphere.api.dto.definition.request.auth.MsAuthManager;
import io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager; import io.metersphere.api.dto.definition.request.dns.MsDNSCacheManager;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor; import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
@ -37,6 +38,7 @@ import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory; import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.FileUtils; import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.HashTreeUtil;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.constants.RunModeConstants; import io.metersphere.constants.RunModeConstants;
import io.metersphere.jmeter.utils.ScriptEngineUtils; import io.metersphere.jmeter.utils.ScriptEngineUtils;
@ -280,6 +282,20 @@ public class MsHTTPSamplerProxy extends MsTestElement {
this.setScript(httpConfig, httpSamplerTree, config, false); this.setScript(httpConfig, httpSamplerTree, config, false);
} }
HashTreeUtil hashTreeUtil = new HashTreeUtil();
//增加误报断言
if (httpConfig != null) {
if(CollectionUtils.isNotEmpty(httpConfig.getErrorReportAssertions())){
for (MsAssertions assertion : httpConfig.getErrorReportAssertions()) {
assertion.toHashTree(httpSamplerTree, assertion.getHashTree(), config);
}
}
if(CollectionUtils.isNotEmpty(httpConfig.getAssertions())){
for (MsAssertions assertion : httpConfig.getAssertions()) {
assertion.toHashTree(httpSamplerTree, assertion.getHashTree(), config);
}
}
}
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
for (MsTestElement el : hashTree) { for (MsTestElement el : hashTree) {
if (el.getEnvironmentId() == null) { if (el.getEnvironmentId() == null) {
@ -289,6 +305,10 @@ public class MsHTTPSamplerProxy extends MsTestElement {
el.setEnvironmentId(this.getEnvironmentId()); el.setEnvironmentId(this.getEnvironmentId());
} }
} }
if (el instanceof MsAssertions) {
//断言设置需要和全局断言误报进行去重
el = hashTreeUtil.duplicateRegexInAssertions(httpConfig.getAssertions(), (MsAssertions) el);
}
el.toHashTree(httpSamplerTree, el.getHashTree(), config); el.toHashTree(httpSamplerTree, el.getHashTree(), config);
} }
} }
@ -386,6 +406,10 @@ public class MsHTTPSamplerProxy extends MsTestElement {
httpConfig.setPreProcessor(environmentConfig.getPreProcessor()); httpConfig.setPreProcessor(environmentConfig.getPreProcessor());
httpConfig.setPostProcessor(environmentConfig.getPostProcessor()); httpConfig.setPostProcessor(environmentConfig.getPostProcessor());
httpConfig.setGlobalScriptConfig(environmentConfig.getGlobalScriptConfig()); httpConfig.setGlobalScriptConfig(environmentConfig.getGlobalScriptConfig());
httpConfig.setAssertions(environmentConfig.getAssertions());
if(environmentConfig.isUseErrorCode()){
httpConfig.setErrorReportAssertions(HashTreeUtil.getErrorReportByProjectId(this.getProjectId()));
}
return httpConfig; return httpConfig;
} }
} }
@ -725,22 +749,22 @@ public class MsHTTPSamplerProxy extends MsTestElement {
list.stream(). list.stream().
filter(KeyValue::isValid). filter(KeyValue::isValid).
filter(KeyValue::isEnable).forEach(keyValue -> { filter(KeyValue::isEnable).forEach(keyValue -> {
try { try {
String value = StringUtils.isNotEmpty(keyValue.getValue()) && keyValue.getValue().startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(keyValue.getValue()) : keyValue.getValue(); String value = StringUtils.isNotEmpty(keyValue.getValue()) && keyValue.getValue().startsWith("@") ? ScriptEngineUtils.buildFunctionCallString(keyValue.getValue()) : keyValue.getValue();
HTTPArgument httpArgument = new HTTPArgument(keyValue.getName(), value); HTTPArgument httpArgument = new HTTPArgument(keyValue.getName(), value);
if (keyValue.getValue() == null) { if (keyValue.getValue() == null) {
httpArgument.setValue(""); httpArgument.setValue("");
} }
httpArgument.setAlwaysEncoded(keyValue.isUrlEncode()); httpArgument.setAlwaysEncoded(keyValue.isUrlEncode());
if (StringUtils.isNotBlank(keyValue.getContentType())) { if (StringUtils.isNotBlank(keyValue.getContentType())) {
httpArgument.setContentType(keyValue.getContentType()); httpArgument.setContentType(keyValue.getContentType());
} }
arguments.addArgument(httpArgument); arguments.addArgument(httpArgument);
} catch (Exception e) { } catch (Exception e) {
} }
} }
); );
return arguments; return arguments;
} }

View File

@ -1,5 +1,6 @@
package io.metersphere.api.dto.scenario; package io.metersphere.api.dto.scenario;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor; import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.api.dto.scenario.environment.GlobalScriptConfig; import io.metersphere.api.dto.scenario.environment.GlobalScriptConfig;
@ -29,6 +30,8 @@ public class HttpConfig {
private MsJSR223PostProcessor postProcessor; private MsJSR223PostProcessor postProcessor;
private GlobalScriptConfig globalScriptConfig; private GlobalScriptConfig globalScriptConfig;
private ApiModuleMapper apiModuleMapper; private ApiModuleMapper apiModuleMapper;
private List<MsAssertions> assertions;
private List<MsAssertions> errorReportAssertions;
private String description; private String description;

View File

@ -1,6 +1,7 @@
package io.metersphere.api.dto.scenario.environment; package io.metersphere.api.dto.scenario.environment;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor; import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor; import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor; import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
@ -30,6 +31,8 @@ public class EnvironmentConfig {
//全局前后置脚本都配置 //全局前后置脚本都配置
private GlobalScriptConfig globalScriptConfig; private GlobalScriptConfig globalScriptConfig;
private JSONObject authManager; private JSONObject authManager;
private List<MsAssertions> assertions;
private boolean useErrorCode;
public EnvironmentConfig() { public EnvironmentConfig() {
this.commonConfig = new CommonConfig(); this.commonConfig = new CommonConfig();

View File

@ -3,6 +3,7 @@ package io.metersphere.api.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.cache.TestPlanReportExecuteCatch; import io.metersphere.api.cache.TestPlanReportExecuteCatch;
import io.metersphere.api.dto.ErrorReportLibraryParseDTO;
import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult; import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
@ -12,6 +13,7 @@ import io.metersphere.base.mapper.TestCaseReviewApiCaseMapper;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper; import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.commons.constants.*; import io.metersphere.commons.constants.*;
import io.metersphere.commons.utils.DateUtils; import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.ErrorReportLibraryUtil;
import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils; import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.dto.RequestResult; import io.metersphere.dto.RequestResult;
@ -64,7 +66,6 @@ public class ApiDefinitionExecResultService {
private TestPlanTestCaseService testPlanTestCaseService; private TestPlanTestCaseService testPlanTestCaseService;
@Resource @Resource
private ApiTestCaseService apiTestCaseService; private ApiTestCaseService apiTestCaseService;
public void saveApiResult(List<RequestResult> requestResults, ResultDTO dto) { public void saveApiResult(List<RequestResult> requestResults, ResultDTO dto) {
boolean isFirst = true; boolean isFirst = true;
int count = requestResults.stream() int count = requestResults.stream()
@ -321,6 +322,7 @@ public class ApiDefinitionExecResultService {
private ApiDefinitionExecResult save(RequestResult item, String reportId, String console, int expectProcessResultCount, String type, String testId, boolean isFirst) { private ApiDefinitionExecResult save(RequestResult item, String reportId, String console, int expectProcessResultCount, String type, String testId, boolean isFirst) {
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) { if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
ErrorReportLibraryParseDTO errorCodeDTO = ErrorReportLibraryUtil.parseAssertions(item);
ApiDefinitionExecResult saveResult = apiDefinitionExecResultMapper.selectByPrimaryKey(reportId); ApiDefinitionExecResult saveResult = apiDefinitionExecResultMapper.selectByPrimaryKey(reportId);
if (saveResult == null) { if (saveResult == null) {
saveResult = new ApiDefinitionExecResult(); saveResult = new ApiDefinitionExecResult();
@ -331,7 +333,11 @@ public class ApiDefinitionExecResultService {
saveResult.setName(item.getName()); saveResult.setName(item.getName());
saveResult.setType(type); saveResult.setType(type);
saveResult.setCreateTime(item.getStartTime()); saveResult.setCreateTime(item.getStartTime());
String status = item.isSuccess() ? "success" : "error"; String status = item.isSuccess() ? ExecuteResult.success.name() : ExecuteResult.error.name();
if(errorCodeDTO.getErrorCodeList() != null){
status = ExecuteResult.errorCode.name();
saveResult.setErrorCode(errorCodeDTO.getErrorCodeStr());
}
saveResult.setName(editStatus(type, status, saveResult.getCreateTime(), saveResult.getId(), testId)); saveResult.setName(editStatus(type, status, saveResult.getCreateTime(), saveResult.getId(), testId));
saveResult.setStatus(status); saveResult.setStatus(status);
saveResult.setResourceId(item.getName()); saveResult.setResourceId(item.getName());

View File

@ -1,8 +1,11 @@
package io.metersphere.api.service; package io.metersphere.api.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.ErrorReportLibraryParseDTO;
import io.metersphere.base.domain.ApiScenarioReportResult; import io.metersphere.base.domain.ApiScenarioReportResult;
import io.metersphere.base.mapper.ApiScenarioReportResultMapper; import io.metersphere.base.mapper.ApiScenarioReportResultMapper;
import io.metersphere.commons.constants.ExecuteResult;
import io.metersphere.commons.utils.ErrorReportLibraryUtil;
import io.metersphere.dto.RequestResult; import io.metersphere.dto.RequestResult;
import io.metersphere.utils.LoggerUtil; import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
@ -36,6 +39,8 @@ public class ApiScenarioReportResultService {
private ApiScenarioReportResult newApiScenarioReportResult(String reportId, RequestResult result) { private ApiScenarioReportResult newApiScenarioReportResult(String reportId, RequestResult result) {
ApiScenarioReportResult report = new ApiScenarioReportResult(); ApiScenarioReportResult report = new ApiScenarioReportResult();
//解析误报内容
ErrorReportLibraryParseDTO errorCodeDTO = ErrorReportLibraryUtil.parseAssertions(result);
report.setId(UUID.randomUUID().toString()); report.setId(UUID.randomUUID().toString());
result.setEndTime(System.currentTimeMillis()); result.setEndTime(System.currentTimeMillis());
if (result.getResponseResult() != null) { if (result.getResponseResult() != null) {
@ -55,7 +60,12 @@ public class ApiScenarioReportResultService {
report.setTotalAssertions(Long.parseLong(result.getTotalAssertions() + "")); report.setTotalAssertions(Long.parseLong(result.getTotalAssertions() + ""));
report.setPassAssertions(Long.parseLong(result.getPassAssertions() + "")); report.setPassAssertions(Long.parseLong(result.getPassAssertions() + ""));
report.setCreateTime(System.currentTimeMillis()); report.setCreateTime(System.currentTimeMillis());
report.setStatus(result.getError() == 0 ? "Success" : "Error"); String status = result.getError() == 0 ? ExecuteResult.Success.name() : ExecuteResult.Error.name();
if(CollectionUtils.isNotEmpty(errorCodeDTO.getErrorCodeList())){
status = ExecuteResult.errorCode.name();
report.setErrorCode(errorCodeDTO.getErrorCodeStr());
}
report.setStatus(status);
report.setRequestTime(result.getEndTime() - result.getStartTime()); report.setRequestTime(result.getEndTime() - result.getStartTime());
report.setContent(JSON.toJSONString(result).getBytes(StandardCharsets.UTF_8)); report.setContent(JSON.toJSONString(result).getBytes(StandardCharsets.UTF_8));
return report; return report;

View File

@ -110,27 +110,34 @@ public class ApiScenarioReportStructureService {
} }
} }
private void scenarioCalculate(List<StepTreeDTO> dtoList, AtomicLong isError) { private void scenarioCalculate(List<StepTreeDTO> dtoList, AtomicLong isError, AtomicLong isErrorReport) {
for (StepTreeDTO step : dtoList) { for (StepTreeDTO step : dtoList) {
if (step.getValue() != null && step.getValue().getError() > 0) { if(step.getValue() != null && StringUtils.isNotEmpty(step.getErrorCode())){
isErrorReport.set(isErrorReport.longValue() + 1);
break;
}else if (step.getValue() != null && step.getValue().getError() > 0) {
isError.set(isError.longValue() + 1); isError.set(isError.longValue() + 1);
break; break;
} else if (CollectionUtils.isNotEmpty(step.getChildren())) { } else if (CollectionUtils.isNotEmpty(step.getChildren())) {
scenarioCalculate(step.getChildren(), isError); scenarioCalculate(step.getChildren(), isError,isErrorReport);
} }
} }
} }
private void calculate(List<StepTreeDTO> dtoList, AtomicLong totalScenario, AtomicLong scenarioError, AtomicLong totalTime) { private void calculate(List<StepTreeDTO> dtoList, AtomicLong totalScenario, AtomicLong scenarioError, AtomicLong totalTime,AtomicLong errorReport) {
for (StepTreeDTO step : dtoList) { for (StepTreeDTO step : dtoList) {
if (StringUtils.equals(step.getType(), "scenario")) { if (StringUtils.equals(step.getType(), "scenario")) {
totalScenario.set((totalScenario.longValue() + 1)); totalScenario.set((totalScenario.longValue() + 1));
// 失败结果数量 // 失败结果数量
AtomicLong error = new AtomicLong(); AtomicLong error = new AtomicLong();
scenarioCalculate(step.getChildren(), error); AtomicLong errorCode = new AtomicLong();
scenarioCalculate(step.getChildren(), error,errorCode);
if (error.longValue() > 0) { if (error.longValue() > 0) {
scenarioError.set((scenarioError.longValue() + 1)); scenarioError.set((scenarioError.longValue() + 1));
} }
if (errorCode.longValue() > 0) {
errorReport.set((errorReport.longValue() + 1));
}
} else if (step.getValue() != null) { } else if (step.getValue() != null) {
if (step.getValue().getStartTime() == 0 || step.getValue().getEndTime() == 0) { if (step.getValue().getStartTime() == 0 || step.getValue().getEndTime() == 0) {
totalTime.set(totalTime.longValue() + 0); totalTime.set(totalTime.longValue() + 0);
@ -139,19 +146,23 @@ public class ApiScenarioReportStructureService {
} }
} }
if (CollectionUtils.isNotEmpty(step.getChildren())) { if (CollectionUtils.isNotEmpty(step.getChildren())) {
calculate(step.getChildren(), totalScenario, scenarioError, totalTime); calculate(step.getChildren(), totalScenario, scenarioError, totalTime,errorReport);
} }
} }
} }
private void calculateStep(List<StepTreeDTO> dtoList, AtomicLong stepError, AtomicLong stepTotal) { private void calculateStep(List<StepTreeDTO> dtoList, AtomicLong stepError, AtomicLong stepTotal,AtomicLong stepErrorCode) {
for (StepTreeDTO step : dtoList) { for (StepTreeDTO step : dtoList) {
// 失败结果数量 // 失败结果数量
AtomicLong error = new AtomicLong(); AtomicLong error = new AtomicLong();
scenarioCalculate(step.getChildren(), error); AtomicLong errorReport = new AtomicLong();
scenarioCalculate(step.getChildren(), error,errorReport);
if (error.longValue() > 0) { if (error.longValue() > 0) {
stepError.set((stepError.longValue() + 1)); stepError.set((stepError.longValue() + 1));
} }
if (errorReport.longValue() > 0) {
stepErrorCode.set((stepErrorCode.longValue() + 1));
}
if (CollectionUtils.isNotEmpty(step.getChildren())) { if (CollectionUtils.isNotEmpty(step.getChildren())) {
stepTotal.set((stepTotal.longValue() + step.getChildren().size())); stepTotal.set((stepTotal.longValue() + step.getChildren().size()));
} }
@ -168,19 +179,35 @@ public class ApiScenarioReportStructureService {
for (int i = 0; i < reportResults.size(); i++) { for (int i = 0; i < reportResults.size(); i++) {
if (i == 0) { if (i == 0) {
dto.setValue(JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class)); dto.setValue(JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class));
dto.setErrorCode(reportResults.get(0).getErrorCode());
} else { } else {
StepTreeDTO step = new StepTreeDTO(dto.getLabel(), UUID.randomUUID().toString(), dto.getType(), (i + 1)); StepTreeDTO step = new StepTreeDTO(dto.getLabel(), UUID.randomUUID().toString(), dto.getType(), (i + 1));
step.setValue(JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class)); step.setValue(JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class));
step.setErrorCode(reportResults.get(i).getErrorCode());
dtoList.add(step); dtoList.add(step);
} }
} }
} else { } else {
String content = new String(reportResults.get(0).getContent(), StandardCharsets.UTF_8); String content = new String(reportResults.get(0).getContent(), StandardCharsets.UTF_8);
dto.setValue(JSON.parseObject(content, RequestResult.class)); dto.setValue(JSON.parseObject(content, RequestResult.class));
dto.setErrorCode(reportResults.get(0).getErrorCode());
} }
} }
if (CollectionUtils.isNotEmpty(dto.getChildren())) { if (CollectionUtils.isNotEmpty(dto.getChildren())) {
reportFormatting(dto.getChildren(), maps); reportFormatting(dto.getChildren(), maps);
if(StringUtils.isEmpty(dto.getErrorCode())){
//统计child的errorCode
List<String> childErrorCodeList = new ArrayList<>();
for (StepTreeDTO child : dto.getChildren()) {
if(StringUtils.isNotEmpty(child.getErrorCode()) && !childErrorCodeList.contains(child.getErrorCode())){
childErrorCodeList.add(child.getErrorCode());
}
}
if(CollectionUtils.isNotEmpty(childErrorCodeList)){
dto.setErrorCode(StringUtils.join(childErrorCodeList,","));
}
}
} }
} }
// 循环步骤请求从新排序 // 循环步骤请求从新排序
@ -208,40 +235,38 @@ public class ApiScenarioReportStructureService {
if (CollectionUtils.isNotEmpty(reportStructureWithBLOBs) && CollectionUtils.isNotEmpty(reportResults)) { if (CollectionUtils.isNotEmpty(reportStructureWithBLOBs) && CollectionUtils.isNotEmpty(reportResults)) {
reportDTO.setTotal(reportResults.size()); reportDTO.setTotal(reportResults.size());
reportDTO.setError(reportResults.stream().filter(e -> StringUtils.equals(e.getStatus(), "Error")).collect(Collectors.toList()).size()); reportDTO.setError(reportResults.stream().filter(e -> StringUtils.equals(e.getStatus(), "Error")).collect(Collectors.toList()).size());
reportDTO.setErrorCode(reportResults.stream().filter(e -> StringUtils.isNotEmpty(e.getErrorCode())).collect(Collectors.toList()).size());
reportDTO.setPassAssertions(reportResults.stream().mapToLong(ApiScenarioReportResult::getPassAssertions).sum()); reportDTO.setPassAssertions(reportResults.stream().mapToLong(ApiScenarioReportResult::getPassAssertions).sum());
reportDTO.setTotalAssertions(reportResults.stream().mapToLong(ApiScenarioReportResult::getTotalAssertions).sum()); reportDTO.setTotalAssertions(reportResults.stream().mapToLong(ApiScenarioReportResult::getTotalAssertions).sum());
ApiScenarioReportStructureWithBLOBs scenarioReportStructure = reportStructureWithBLOBs.get(0); ApiScenarioReportStructureWithBLOBs scenarioReportStructure = reportStructureWithBLOBs.get(0);
List<StepTreeDTO> stepList = JSONArray.parseArray(new String(scenarioReportStructure.getResourceTree(), StandardCharsets.UTF_8), StepTreeDTO.class); List<StepTreeDTO> stepList = JSONArray.parseArray(new String(scenarioReportStructure.getResourceTree(), StandardCharsets.UTF_8), StepTreeDTO.class);
// 匹配结果 // 匹配结果
Map<String, List<ApiScenarioReportResult>> maps = reportResults.stream().collect(Collectors.groupingBy(ApiScenarioReportResult::getResourceId)); Map<String, List<ApiScenarioReportResult>> maps = reportResults.stream().collect(Collectors.groupingBy(ApiScenarioReportResult::getResourceId));
this.reportFormatting(stepList, maps); this.reportFormatting(stepList, maps);
// 统计场景和步骤成功失败总量 // 统计场景数据
AtomicLong totalScenario = new AtomicLong(); AtomicLong totalScenario = new AtomicLong();
AtomicLong scenarioError = new AtomicLong(); AtomicLong scenarioError = new AtomicLong();
AtomicLong totalTime = new AtomicLong(); AtomicLong totalTime = new AtomicLong();
AtomicLong errorReport = new AtomicLong();
calculate(stepList, totalScenario, scenarioError, totalTime); calculate(stepList, totalScenario, scenarioError, totalTime,errorReport);
reportDTO.setTotalTime(totalTime.longValue()); reportDTO.setTotalTime(totalTime.longValue());
reportDTO.setScenarioTotal(totalScenario.longValue()); reportDTO.setScenarioTotal(totalScenario.longValue());
reportDTO.setScenarioError(scenarioError.longValue()); reportDTO.setScenarioError(scenarioError.longValue());
reportDTO.setScenarioSuccess((totalScenario.longValue() - scenarioError.longValue())); reportDTO.setScenarioErrorReport(errorReport.longValue());
reportDTO.setScenarioSuccess((totalScenario.longValue() - scenarioError.longValue() -errorReport.longValue()));
//统计步骤数据
AtomicLong stepError = new AtomicLong(); AtomicLong stepError = new AtomicLong();
AtomicLong stepErrorCode = new AtomicLong();
AtomicLong stepTotal = new AtomicLong(); AtomicLong stepTotal = new AtomicLong();
calculateStep(stepList, stepError, stepTotal); calculateStep(stepList, stepError, stepTotal,stepErrorCode);
reportDTO.setScenarioStepTotal(stepTotal.longValue()); reportDTO.setScenarioStepTotal(stepTotal.longValue());
reportDTO.setScenarioStepError(stepError.longValue()); reportDTO.setScenarioStepError(stepError.longValue());
reportDTO.setScenarioStepSuccess((stepList.size() - stepError.longValue())); reportDTO.setScenarioStepErrorReport(stepErrorCode.longValue());
reportDTO.setScenarioStepSuccess((stepList.size() - stepError.longValue() - stepErrorCode.longValue()));
reportDTO.setConsole(scenarioReportStructure.getConsole()); reportDTO.setConsole(scenarioReportStructure.getConsole());
reportDTO.setSteps(stepList); reportDTO.setSteps(stepList);
} }
return reportDTO; return reportDTO;
} }
} }

View File

@ -29,6 +29,8 @@ public class ApiDefinitionExecResult implements Serializable {
private String versionId; private String versionId;
private String errorCode;
private String content; private String content;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -913,6 +913,76 @@ public class ApiDefinitionExecResultExample {
addCriterion("version_id not between", value1, value2, "versionId"); addCriterion("version_id not between", value1, value2, "versionId");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andErrorCodeIsNull() {
addCriterion("error_code is null");
return (Criteria) this;
}
public Criteria andErrorCodeIsNotNull() {
addCriterion("error_code is not null");
return (Criteria) this;
}
public Criteria andErrorCodeEqualTo(String value) {
addCriterion("error_code =", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotEqualTo(String value) {
addCriterion("error_code <>", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeGreaterThan(String value) {
addCriterion("error_code >", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeGreaterThanOrEqualTo(String value) {
addCriterion("error_code >=", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLessThan(String value) {
addCriterion("error_code <", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLessThanOrEqualTo(String value) {
addCriterion("error_code <=", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLike(String value) {
addCriterion("error_code like", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotLike(String value) {
addCriterion("error_code not like", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeIn(List<String> values) {
addCriterion("error_code in", values, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotIn(List<String> values) {
addCriterion("error_code not in", values, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeBetween(String value1, String value2) {
addCriterion("error_code between", value1, value2, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotBetween(String value1, String value2) {
addCriterion("error_code not between", value1, value2, "errorCode");
return (Criteria) this;
}
} }
public static class Criteria extends GeneratedCriteria { public static class Criteria extends GeneratedCriteria {

View File

@ -0,0 +1,17 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ApiDefinitionExecResultWithBLOBs extends ApiDefinitionExecResult implements Serializable {
private String content;
private String errorCode;
private static final long serialVersionUID = 1L;
}

View File

@ -1,8 +1,7 @@
package io.metersphere.base.domain; package io.metersphere.base.domain;
import lombok.Data;
import java.io.Serializable; import java.io.Serializable;
import lombok.Data;
@Data @Data
public class ApiScenarioReportResult implements Serializable { public class ApiScenarioReportResult implements Serializable {
@ -22,6 +21,8 @@ public class ApiScenarioReportResult implements Serializable {
private Long passAssertions; private Long passAssertions;
private String errorCode;
private byte[] content; private byte[] content;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;

View File

@ -623,6 +623,76 @@ public class ApiScenarioReportResultExample {
addCriterion("pass_assertions not between", value1, value2, "passAssertions"); addCriterion("pass_assertions not between", value1, value2, "passAssertions");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andErrorCodeIsNull() {
addCriterion("error_code is null");
return (Criteria) this;
}
public Criteria andErrorCodeIsNotNull() {
addCriterion("error_code is not null");
return (Criteria) this;
}
public Criteria andErrorCodeEqualTo(String value) {
addCriterion("error_code =", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotEqualTo(String value) {
addCriterion("error_code <>", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeGreaterThan(String value) {
addCriterion("error_code >", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeGreaterThanOrEqualTo(String value) {
addCriterion("error_code >=", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLessThan(String value) {
addCriterion("error_code <", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLessThanOrEqualTo(String value) {
addCriterion("error_code <=", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLike(String value) {
addCriterion("error_code like", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotLike(String value) {
addCriterion("error_code not like", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeIn(List<String> values) {
addCriterion("error_code in", values, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotIn(List<String> values) {
addCriterion("error_code not in", values, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeBetween(String value1, String value2) {
addCriterion("error_code between", value1, value2, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotBetween(String value1, String value2) {
addCriterion("error_code not between", value1, value2, "errorCode");
return (Criteria) this;
}
} }
public static class Criteria extends GeneratedCriteria { public static class Criteria extends GeneratedCriteria {

View File

@ -0,0 +1,15 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ApiScenarioReportResultWithBLOBs extends ApiScenarioReportResult implements Serializable {
private String errorCode;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,27 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
@Data
public class ErrorReportLibrary implements Serializable {
private String id;
private String projectId;
private Long createTime;
private Long updateTime;
private String createUser;
private String updateUser;
private String errorCode;
private String matchType;
private Boolean status;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,800 @@
package io.metersphere.base.domain;
import java.util.ArrayList;
import java.util.List;
public class ErrorReportLibraryExample {
protected String orderByClause;
protected boolean distinct;
protected List<Criteria> oredCriteria;
public ErrorReportLibraryExample() {
oredCriteria = new ArrayList<Criteria>();
}
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
public String getOrderByClause() {
return orderByClause;
}
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
public boolean isDistinct() {
return distinct;
}
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria();
return criteria;
}
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andProjectIdIsNull() {
addCriterion("project_id is null");
return (Criteria) this;
}
public Criteria andProjectIdIsNotNull() {
addCriterion("project_id is not null");
return (Criteria) this;
}
public Criteria andProjectIdEqualTo(String value) {
addCriterion("project_id =", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotEqualTo(String value) {
addCriterion("project_id <>", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdGreaterThan(String value) {
addCriterion("project_id >", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
addCriterion("project_id >=", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLessThan(String value) {
addCriterion("project_id <", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLessThanOrEqualTo(String value) {
addCriterion("project_id <=", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLike(String value) {
addCriterion("project_id like", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotLike(String value) {
addCriterion("project_id not like", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdIn(List<String> values) {
addCriterion("project_id in", values, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotIn(List<String> values) {
addCriterion("project_id not in", values, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdBetween(String value1, String value2) {
addCriterion("project_id between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotBetween(String value1, String value2) {
addCriterion("project_id not between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andCreateTimeIsNull() {
addCriterion("create_time is null");
return (Criteria) this;
}
public Criteria andCreateTimeIsNotNull() {
addCriterion("create_time is not null");
return (Criteria) this;
}
public Criteria andCreateTimeEqualTo(Long value) {
addCriterion("create_time =", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotEqualTo(Long value) {
addCriterion("create_time <>", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThan(Long value) {
addCriterion("create_time >", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThanOrEqualTo(Long value) {
addCriterion("create_time >=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThan(Long value) {
addCriterion("create_time <", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThanOrEqualTo(Long value) {
addCriterion("create_time <=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeIn(List<Long> values) {
addCriterion("create_time in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotIn(List<Long> values) {
addCriterion("create_time not in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeBetween(Long value1, Long value2) {
addCriterion("create_time between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotBetween(Long value1, Long value2) {
addCriterion("create_time not between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andUpdateTimeIsNull() {
addCriterion("update_time is null");
return (Criteria) this;
}
public Criteria andUpdateTimeIsNotNull() {
addCriterion("update_time is not null");
return (Criteria) this;
}
public Criteria andUpdateTimeEqualTo(Long value) {
addCriterion("update_time =", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotEqualTo(Long value) {
addCriterion("update_time <>", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeGreaterThan(Long value) {
addCriterion("update_time >", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeGreaterThanOrEqualTo(Long value) {
addCriterion("update_time >=", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeLessThan(Long value) {
addCriterion("update_time <", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeLessThanOrEqualTo(Long value) {
addCriterion("update_time <=", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeIn(List<Long> values) {
addCriterion("update_time in", values, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotIn(List<Long> values) {
addCriterion("update_time not in", values, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeBetween(Long value1, Long value2) {
addCriterion("update_time between", value1, value2, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotBetween(Long value1, Long value2) {
addCriterion("update_time not between", value1, value2, "updateTime");
return (Criteria) this;
}
public Criteria andCreateUserIsNull() {
addCriterion("create_user is null");
return (Criteria) this;
}
public Criteria andCreateUserIsNotNull() {
addCriterion("create_user is not null");
return (Criteria) this;
}
public Criteria andCreateUserEqualTo(String value) {
addCriterion("create_user =", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserNotEqualTo(String value) {
addCriterion("create_user <>", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserGreaterThan(String value) {
addCriterion("create_user >", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserGreaterThanOrEqualTo(String value) {
addCriterion("create_user >=", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserLessThan(String value) {
addCriterion("create_user <", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserLessThanOrEqualTo(String value) {
addCriterion("create_user <=", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserLike(String value) {
addCriterion("create_user like", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserNotLike(String value) {
addCriterion("create_user not like", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserIn(List<String> values) {
addCriterion("create_user in", values, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserNotIn(List<String> values) {
addCriterion("create_user not in", values, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserBetween(String value1, String value2) {
addCriterion("create_user between", value1, value2, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserNotBetween(String value1, String value2) {
addCriterion("create_user not between", value1, value2, "createUser");
return (Criteria) this;
}
public Criteria andUpdateUserIsNull() {
addCriterion("update_user is null");
return (Criteria) this;
}
public Criteria andUpdateUserIsNotNull() {
addCriterion("update_user is not null");
return (Criteria) this;
}
public Criteria andUpdateUserEqualTo(String value) {
addCriterion("update_user =", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserNotEqualTo(String value) {
addCriterion("update_user <>", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserGreaterThan(String value) {
addCriterion("update_user >", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserGreaterThanOrEqualTo(String value) {
addCriterion("update_user >=", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserLessThan(String value) {
addCriterion("update_user <", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserLessThanOrEqualTo(String value) {
addCriterion("update_user <=", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserLike(String value) {
addCriterion("update_user like", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserNotLike(String value) {
addCriterion("update_user not like", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserIn(List<String> values) {
addCriterion("update_user in", values, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserNotIn(List<String> values) {
addCriterion("update_user not in", values, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserBetween(String value1, String value2) {
addCriterion("update_user between", value1, value2, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserNotBetween(String value1, String value2) {
addCriterion("update_user not between", value1, value2, "updateUser");
return (Criteria) this;
}
public Criteria andErrorCodeIsNull() {
addCriterion("error_code is null");
return (Criteria) this;
}
public Criteria andErrorCodeIsNotNull() {
addCriterion("error_code is not null");
return (Criteria) this;
}
public Criteria andErrorCodeEqualTo(String value) {
addCriterion("error_code =", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotEqualTo(String value) {
addCriterion("error_code <>", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeGreaterThan(String value) {
addCriterion("error_code >", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeGreaterThanOrEqualTo(String value) {
addCriterion("error_code >=", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLessThan(String value) {
addCriterion("error_code <", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLessThanOrEqualTo(String value) {
addCriterion("error_code <=", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeLike(String value) {
addCriterion("error_code like", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotLike(String value) {
addCriterion("error_code not like", value, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeIn(List<String> values) {
addCriterion("error_code in", values, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotIn(List<String> values) {
addCriterion("error_code not in", values, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeBetween(String value1, String value2) {
addCriterion("error_code between", value1, value2, "errorCode");
return (Criteria) this;
}
public Criteria andErrorCodeNotBetween(String value1, String value2) {
addCriterion("error_code not between", value1, value2, "errorCode");
return (Criteria) this;
}
public Criteria andMatchTypeIsNull() {
addCriterion("match_type is null");
return (Criteria) this;
}
public Criteria andMatchTypeIsNotNull() {
addCriterion("match_type is not null");
return (Criteria) this;
}
public Criteria andMatchTypeEqualTo(String value) {
addCriterion("match_type =", value, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeNotEqualTo(String value) {
addCriterion("match_type <>", value, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeGreaterThan(String value) {
addCriterion("match_type >", value, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeGreaterThanOrEqualTo(String value) {
addCriterion("match_type >=", value, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeLessThan(String value) {
addCriterion("match_type <", value, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeLessThanOrEqualTo(String value) {
addCriterion("match_type <=", value, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeLike(String value) {
addCriterion("match_type like", value, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeNotLike(String value) {
addCriterion("match_type not like", value, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeIn(List<String> values) {
addCriterion("match_type in", values, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeNotIn(List<String> values) {
addCriterion("match_type not in", values, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeBetween(String value1, String value2) {
addCriterion("match_type between", value1, value2, "matchType");
return (Criteria) this;
}
public Criteria andMatchTypeNotBetween(String value1, String value2) {
addCriterion("match_type not between", value1, value2, "matchType");
return (Criteria) this;
}
public Criteria andStatusIsNull() {
addCriterion("`status` is null");
return (Criteria) this;
}
public Criteria andStatusIsNotNull() {
addCriterion("`status` is not null");
return (Criteria) this;
}
public Criteria andStatusEqualTo(Boolean value) {
addCriterion("`status` =", value, "status");
return (Criteria) this;
}
public Criteria andStatusNotEqualTo(Boolean value) {
addCriterion("`status` <>", value, "status");
return (Criteria) this;
}
public Criteria andStatusGreaterThan(Boolean value) {
addCriterion("`status` >", value, "status");
return (Criteria) this;
}
public Criteria andStatusGreaterThanOrEqualTo(Boolean value) {
addCriterion("`status` >=", value, "status");
return (Criteria) this;
}
public Criteria andStatusLessThan(Boolean value) {
addCriterion("`status` <", value, "status");
return (Criteria) this;
}
public Criteria andStatusLessThanOrEqualTo(Boolean value) {
addCriterion("`status` <=", value, "status");
return (Criteria) this;
}
public Criteria andStatusIn(List<Boolean> values) {
addCriterion("`status` in", values, "status");
return (Criteria) this;
}
public Criteria andStatusNotIn(List<Boolean> values) {
addCriterion("`status` not in", values, "status");
return (Criteria) this;
}
public Criteria andStatusBetween(Boolean value1, Boolean value2) {
addCriterion("`status` between", value1, value2, "status");
return (Criteria) this;
}
public Criteria andStatusNotBetween(Boolean value1, Boolean value2) {
addCriterion("`status` not between", value1, value2, "status");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
protected Criteria() {
super();
}
}
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
}
}

View File

@ -0,0 +1,17 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ErrorReportLibraryWithBLOBs extends ErrorReportLibrary implements Serializable {
private String content;
private String description;
private static final long serialVersionUID = 1L;
}

View File

@ -14,6 +14,7 @@
<result column="actuator" jdbcType="VARCHAR" property="actuator" /> <result column="actuator" jdbcType="VARCHAR" property="actuator" />
<result column="trigger_mode" jdbcType="VARCHAR" property="triggerMode" /> <result column="trigger_mode" jdbcType="VARCHAR" property="triggerMode" />
<result column="version_id" jdbcType="VARCHAR" property="versionId" /> <result column="version_id" jdbcType="VARCHAR" property="versionId" />
<result column="error_code" jdbcType="VARCHAR" property="errorCode" />
</resultMap> </resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiDefinitionExecResult"> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiDefinitionExecResult">
<result column="content" jdbcType="LONGVARCHAR" property="content" /> <result column="content" jdbcType="LONGVARCHAR" property="content" />
@ -78,7 +79,7 @@
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, `name`, resource_id, `status`, user_id, start_time, end_time, create_time, `type`, id, `name`, resource_id, `status`, user_id, start_time, end_time, create_time, `type`,
actuator, trigger_mode, version_id actuator, trigger_mode, version_id, error_code
</sql> </sql>
<sql id="Blob_Column_List"> <sql id="Blob_Column_List">
content content
@ -135,13 +136,13 @@
insert into api_definition_exec_result (id, `name`, resource_id, insert into api_definition_exec_result (id, `name`, resource_id,
`status`, user_id, start_time, `status`, user_id, start_time,
end_time, create_time, `type`, end_time, create_time, `type`,
actuator, trigger_mode, version_id, actuator, trigger_mode, version_id,
content) error_code, content)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR}, values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR},
#{status,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{startTime,jdbcType=BIGINT}, #{status,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{startTime,jdbcType=BIGINT},
#{endTime,jdbcType=BIGINT}, #{createTime,jdbcType=BIGINT}, #{type,jdbcType=VARCHAR}, #{endTime,jdbcType=BIGINT}, #{createTime,jdbcType=BIGINT}, #{type,jdbcType=VARCHAR},
#{actuator,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}, #{versionId,jdbcType=VARCHAR}, #{actuator,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}, #{versionId,jdbcType=VARCHAR},
#{content,jdbcType=LONGVARCHAR}) #{errorCode,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARCHAR})
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiDefinitionExecResult"> <insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiDefinitionExecResult">
insert into api_definition_exec_result insert into api_definition_exec_result
@ -182,6 +183,9 @@
<if test="versionId != null"> <if test="versionId != null">
version_id, version_id,
</if> </if>
<if test="errorCode != null">
error_code,
</if>
<if test="content != null"> <if test="content != null">
content, content,
</if> </if>
@ -223,6 +227,9 @@
<if test="versionId != null"> <if test="versionId != null">
#{versionId,jdbcType=VARCHAR}, #{versionId,jdbcType=VARCHAR},
</if> </if>
<if test="errorCode != null">
#{errorCode,jdbcType=VARCHAR},
</if>
<if test="content != null"> <if test="content != null">
#{content,jdbcType=LONGVARCHAR}, #{content,jdbcType=LONGVARCHAR},
</if> </if>
@ -273,6 +280,9 @@
<if test="record.versionId != null"> <if test="record.versionId != null">
version_id = #{record.versionId,jdbcType=VARCHAR}, version_id = #{record.versionId,jdbcType=VARCHAR},
</if> </if>
<if test="record.errorCode != null">
error_code = #{record.errorCode,jdbcType=VARCHAR},
</if>
<if test="record.content != null"> <if test="record.content != null">
content = #{record.content,jdbcType=LONGVARCHAR}, content = #{record.content,jdbcType=LONGVARCHAR},
</if> </if>
@ -295,6 +305,7 @@
actuator = #{record.actuator,jdbcType=VARCHAR}, actuator = #{record.actuator,jdbcType=VARCHAR},
trigger_mode = #{record.triggerMode,jdbcType=VARCHAR}, trigger_mode = #{record.triggerMode,jdbcType=VARCHAR},
version_id = #{record.versionId,jdbcType=VARCHAR}, version_id = #{record.versionId,jdbcType=VARCHAR},
error_code = #{record.errorCode,jdbcType=VARCHAR},
content = #{record.content,jdbcType=LONGVARCHAR} content = #{record.content,jdbcType=LONGVARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
@ -313,7 +324,8 @@
`type` = #{record.type,jdbcType=VARCHAR}, `type` = #{record.type,jdbcType=VARCHAR},
actuator = #{record.actuator,jdbcType=VARCHAR}, actuator = #{record.actuator,jdbcType=VARCHAR},
trigger_mode = #{record.triggerMode,jdbcType=VARCHAR}, trigger_mode = #{record.triggerMode,jdbcType=VARCHAR},
version_id = #{record.versionId,jdbcType=VARCHAR} version_id = #{record.versionId,jdbcType=VARCHAR},
error_code = #{record.errorCode,jdbcType=VARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
</if> </if>
@ -354,6 +366,9 @@
<if test="versionId != null"> <if test="versionId != null">
version_id = #{versionId,jdbcType=VARCHAR}, version_id = #{versionId,jdbcType=VARCHAR},
</if> </if>
<if test="errorCode != null">
error_code = #{errorCode,jdbcType=VARCHAR},
</if>
<if test="content != null"> <if test="content != null">
content = #{content,jdbcType=LONGVARCHAR}, content = #{content,jdbcType=LONGVARCHAR},
</if> </if>
@ -373,6 +388,7 @@
actuator = #{actuator,jdbcType=VARCHAR}, actuator = #{actuator,jdbcType=VARCHAR},
trigger_mode = #{triggerMode,jdbcType=VARCHAR}, trigger_mode = #{triggerMode,jdbcType=VARCHAR},
version_id = #{versionId,jdbcType=VARCHAR}, version_id = #{versionId,jdbcType=VARCHAR},
error_code = #{errorCode,jdbcType=VARCHAR},
content = #{content,jdbcType=LONGVARCHAR} content = #{content,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
@ -388,7 +404,8 @@
`type` = #{type,jdbcType=VARCHAR}, `type` = #{type,jdbcType=VARCHAR},
actuator = #{actuator,jdbcType=VARCHAR}, actuator = #{actuator,jdbcType=VARCHAR},
trigger_mode = #{triggerMode,jdbcType=VARCHAR}, trigger_mode = #{triggerMode,jdbcType=VARCHAR},
version_id = #{versionId,jdbcType=VARCHAR} version_id = #{versionId,jdbcType=VARCHAR},
error_code = #{errorCode,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
</mapper> </mapper>

View File

@ -10,6 +10,7 @@
<result column="request_time" jdbcType="BIGINT" property="requestTime" /> <result column="request_time" jdbcType="BIGINT" property="requestTime" />
<result column="total_assertions" jdbcType="BIGINT" property="totalAssertions" /> <result column="total_assertions" jdbcType="BIGINT" property="totalAssertions" />
<result column="pass_assertions" jdbcType="BIGINT" property="passAssertions" /> <result column="pass_assertions" jdbcType="BIGINT" property="passAssertions" />
<result column="error_code" jdbcType="VARCHAR" property="errorCode" />
</resultMap> </resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiScenarioReportResult"> <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiScenarioReportResult">
<result column="content" jdbcType="LONGVARBINARY" property="content" /> <result column="content" jdbcType="LONGVARBINARY" property="content" />
@ -74,7 +75,7 @@
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, resource_id, report_id, create_time, `status`, request_time, total_assertions, id, resource_id, report_id, create_time, `status`, request_time, total_assertions,
pass_assertions pass_assertions, error_code
</sql> </sql>
<sql id="Blob_Column_List"> <sql id="Blob_Column_List">
content content
@ -130,12 +131,12 @@
<insert id="insert" parameterType="io.metersphere.base.domain.ApiScenarioReportResult"> <insert id="insert" parameterType="io.metersphere.base.domain.ApiScenarioReportResult">
insert into api_scenario_report_result (id, resource_id, report_id, insert into api_scenario_report_result (id, resource_id, report_id,
create_time, `status`, request_time, create_time, `status`, request_time,
total_assertions, pass_assertions, content total_assertions, pass_assertions, error_code,
) content)
values (#{id,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR}, values (#{id,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{status,jdbcType=VARCHAR}, #{requestTime,jdbcType=BIGINT}, #{createTime,jdbcType=BIGINT}, #{status,jdbcType=VARCHAR}, #{requestTime,jdbcType=BIGINT},
#{totalAssertions,jdbcType=BIGINT}, #{passAssertions,jdbcType=BIGINT}, #{content,jdbcType=LONGVARBINARY} #{totalAssertions,jdbcType=BIGINT}, #{passAssertions,jdbcType=BIGINT}, #{errorCode,jdbcType=VARCHAR},
) #{content,jdbcType=LONGVARBINARY})
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiScenarioReportResult"> <insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiScenarioReportResult">
insert into api_scenario_report_result insert into api_scenario_report_result
@ -164,6 +165,9 @@
<if test="passAssertions != null"> <if test="passAssertions != null">
pass_assertions, pass_assertions,
</if> </if>
<if test="errorCode != null">
error_code,
</if>
<if test="content != null"> <if test="content != null">
content, content,
</if> </if>
@ -193,6 +197,9 @@
<if test="passAssertions != null"> <if test="passAssertions != null">
#{passAssertions,jdbcType=BIGINT}, #{passAssertions,jdbcType=BIGINT},
</if> </if>
<if test="errorCode != null">
#{errorCode,jdbcType=VARCHAR},
</if>
<if test="content != null"> <if test="content != null">
#{content,jdbcType=LONGVARBINARY}, #{content,jdbcType=LONGVARBINARY},
</if> </if>
@ -231,6 +238,9 @@
<if test="record.passAssertions != null"> <if test="record.passAssertions != null">
pass_assertions = #{record.passAssertions,jdbcType=BIGINT}, pass_assertions = #{record.passAssertions,jdbcType=BIGINT},
</if> </if>
<if test="record.errorCode != null">
error_code = #{record.errorCode,jdbcType=VARCHAR},
</if>
<if test="record.content != null"> <if test="record.content != null">
content = #{record.content,jdbcType=LONGVARBINARY}, content = #{record.content,jdbcType=LONGVARBINARY},
</if> </if>
@ -249,6 +259,7 @@
request_time = #{record.requestTime,jdbcType=BIGINT}, request_time = #{record.requestTime,jdbcType=BIGINT},
total_assertions = #{record.totalAssertions,jdbcType=BIGINT}, total_assertions = #{record.totalAssertions,jdbcType=BIGINT},
pass_assertions = #{record.passAssertions,jdbcType=BIGINT}, pass_assertions = #{record.passAssertions,jdbcType=BIGINT},
error_code = #{record.errorCode,jdbcType=VARCHAR},
content = #{record.content,jdbcType=LONGVARBINARY} content = #{record.content,jdbcType=LONGVARBINARY}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
@ -263,7 +274,8 @@
`status` = #{record.status,jdbcType=VARCHAR}, `status` = #{record.status,jdbcType=VARCHAR},
request_time = #{record.requestTime,jdbcType=BIGINT}, request_time = #{record.requestTime,jdbcType=BIGINT},
total_assertions = #{record.totalAssertions,jdbcType=BIGINT}, total_assertions = #{record.totalAssertions,jdbcType=BIGINT},
pass_assertions = #{record.passAssertions,jdbcType=BIGINT} pass_assertions = #{record.passAssertions,jdbcType=BIGINT},
error_code = #{record.errorCode,jdbcType=VARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
</if> </if>
@ -292,6 +304,9 @@
<if test="passAssertions != null"> <if test="passAssertions != null">
pass_assertions = #{passAssertions,jdbcType=BIGINT}, pass_assertions = #{passAssertions,jdbcType=BIGINT},
</if> </if>
<if test="errorCode != null">
error_code = #{errorCode,jdbcType=VARCHAR},
</if>
<if test="content != null"> <if test="content != null">
content = #{content,jdbcType=LONGVARBINARY}, content = #{content,jdbcType=LONGVARBINARY},
</if> </if>
@ -307,6 +322,7 @@
request_time = #{requestTime,jdbcType=BIGINT}, request_time = #{requestTime,jdbcType=BIGINT},
total_assertions = #{totalAssertions,jdbcType=BIGINT}, total_assertions = #{totalAssertions,jdbcType=BIGINT},
pass_assertions = #{passAssertions,jdbcType=BIGINT}, pass_assertions = #{passAssertions,jdbcType=BIGINT},
error_code = #{errorCode,jdbcType=VARCHAR},
content = #{content,jdbcType=LONGVARBINARY} content = #{content,jdbcType=LONGVARBINARY}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
@ -318,7 +334,8 @@
`status` = #{status,jdbcType=VARCHAR}, `status` = #{status,jdbcType=VARCHAR},
request_time = #{requestTime,jdbcType=BIGINT}, request_time = #{requestTime,jdbcType=BIGINT},
total_assertions = #{totalAssertions,jdbcType=BIGINT}, total_assertions = #{totalAssertions,jdbcType=BIGINT},
pass_assertions = #{passAssertions,jdbcType=BIGINT} pass_assertions = #{passAssertions,jdbcType=BIGINT},
error_code = #{errorCode,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
</mapper> </mapper>

View File

@ -0,0 +1,37 @@
package io.metersphere.base.mapper;
import io.metersphere.base.domain.ErrorReportLibrary;
import io.metersphere.base.domain.ErrorReportLibraryExample;
import io.metersphere.base.domain.ErrorReportLibraryWithBLOBs;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface ErrorReportLibraryMapper {
long countByExample(ErrorReportLibraryExample example);
int deleteByExample(ErrorReportLibraryExample example);
int deleteByPrimaryKey(String id);
int insert(ErrorReportLibraryWithBLOBs record);
int insertSelective(ErrorReportLibraryWithBLOBs record);
List<ErrorReportLibraryWithBLOBs> selectByExampleWithBLOBs(ErrorReportLibraryExample example);
List<ErrorReportLibrary> selectByExample(ErrorReportLibraryExample example);
ErrorReportLibraryWithBLOBs selectByPrimaryKey(String id);
int updateByExampleSelective(@Param("record") ErrorReportLibraryWithBLOBs record, @Param("example") ErrorReportLibraryExample example);
int updateByExampleWithBLOBs(@Param("record") ErrorReportLibraryWithBLOBs record, @Param("example") ErrorReportLibraryExample example);
int updateByExample(@Param("record") ErrorReportLibrary record, @Param("example") ErrorReportLibraryExample example);
int updateByPrimaryKeySelective(ErrorReportLibraryWithBLOBs record);
int updateByPrimaryKeyWithBLOBs(ErrorReportLibraryWithBLOBs record);
int updateByPrimaryKey(ErrorReportLibrary record);
}

View File

@ -0,0 +1,356 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.base.mapper.ErrorReportLibraryMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.ErrorReportLibrary">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
<result column="update_user" jdbcType="VARCHAR" property="updateUser" />
<result column="error_code" jdbcType="VARCHAR" property="errorCode" />
<result column="match_type" jdbcType="VARCHAR" property="matchType" />
<result column="status" jdbcType="BIT" property="status" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ErrorReportLibraryWithBLOBs">
<result column="content" jdbcType="LONGVARCHAR" property="content" />
<result column="description" jdbcType="LONGVARCHAR" property="description" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Update_By_Example_Where_Clause">
<where>
<foreach collection="example.oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
id, project_id, create_time, update_time, create_user, update_user, error_code, match_type,
`status`
</sql>
<sql id="Blob_Column_List">
content, description
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.ErrorReportLibraryExample" resultMap="ResultMapWithBLOBs">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from error_report_library
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByExample" parameterType="io.metersphere.base.domain.ErrorReportLibraryExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from error_report_library
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from error_report_library
where id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from error_report_library
where id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.ErrorReportLibraryExample">
delete from error_report_library
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.ErrorReportLibraryWithBLOBs">
insert into error_report_library (id, project_id, create_time,
update_time, create_user, update_user,
error_code, match_type, `status`,
content, description)
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
#{updateTime,jdbcType=BIGINT}, #{createUser,jdbcType=VARCHAR}, #{updateUser,jdbcType=VARCHAR},
#{errorCode,jdbcType=VARCHAR}, #{matchType,jdbcType=VARCHAR}, #{status,jdbcType=BIT},
#{content,jdbcType=LONGVARCHAR}, #{description,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ErrorReportLibraryWithBLOBs">
insert into error_report_library
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="projectId != null">
project_id,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateTime != null">
update_time,
</if>
<if test="createUser != null">
create_user,
</if>
<if test="updateUser != null">
update_user,
</if>
<if test="errorCode != null">
error_code,
</if>
<if test="matchType != null">
match_type,
</if>
<if test="status != null">
`status`,
</if>
<if test="content != null">
content,
</if>
<if test="description != null">
description,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=BIGINT},
</if>
<if test="createUser != null">
#{createUser,jdbcType=VARCHAR},
</if>
<if test="updateUser != null">
#{updateUser,jdbcType=VARCHAR},
</if>
<if test="errorCode != null">
#{errorCode,jdbcType=VARCHAR},
</if>
<if test="matchType != null">
#{matchType,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=BIT},
</if>
<if test="content != null">
#{content,jdbcType=LONGVARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=LONGVARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.ErrorReportLibraryExample" resultType="java.lang.Long">
select count(*) from error_report_library
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update error_report_library
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
</if>
<if test="record.createTime != null">
create_time = #{record.createTime,jdbcType=BIGINT},
</if>
<if test="record.updateTime != null">
update_time = #{record.updateTime,jdbcType=BIGINT},
</if>
<if test="record.createUser != null">
create_user = #{record.createUser,jdbcType=VARCHAR},
</if>
<if test="record.updateUser != null">
update_user = #{record.updateUser,jdbcType=VARCHAR},
</if>
<if test="record.errorCode != null">
error_code = #{record.errorCode,jdbcType=VARCHAR},
</if>
<if test="record.matchType != null">
match_type = #{record.matchType,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
`status` = #{record.status,jdbcType=BIT},
</if>
<if test="record.content != null">
content = #{record.content,jdbcType=LONGVARCHAR},
</if>
<if test="record.description != null">
description = #{record.description,jdbcType=LONGVARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update error_report_library
set id = #{record.id,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
create_user = #{record.createUser,jdbcType=VARCHAR},
update_user = #{record.updateUser,jdbcType=VARCHAR},
error_code = #{record.errorCode,jdbcType=VARCHAR},
match_type = #{record.matchType,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=BIT},
content = #{record.content,jdbcType=LONGVARCHAR},
description = #{record.description,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update error_report_library
set id = #{record.id,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
create_user = #{record.createUser,jdbcType=VARCHAR},
update_user = #{record.updateUser,jdbcType=VARCHAR},
error_code = #{record.errorCode,jdbcType=VARCHAR},
match_type = #{record.matchType,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=BIT}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.ErrorReportLibraryWithBLOBs">
update error_report_library
<set>
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
update_time = #{updateTime,jdbcType=BIGINT},
</if>
<if test="createUser != null">
create_user = #{createUser,jdbcType=VARCHAR},
</if>
<if test="updateUser != null">
update_user = #{updateUser,jdbcType=VARCHAR},
</if>
<if test="errorCode != null">
error_code = #{errorCode,jdbcType=VARCHAR},
</if>
<if test="matchType != null">
match_type = #{matchType,jdbcType=VARCHAR},
</if>
<if test="status != null">
`status` = #{status,jdbcType=BIT},
</if>
<if test="content != null">
content = #{content,jdbcType=LONGVARCHAR},
</if>
<if test="description != null">
description = #{description,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.ErrorReportLibraryWithBLOBs">
update error_report_library
set project_id = #{projectId,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
create_user = #{createUser,jdbcType=VARCHAR},
update_user = #{updateUser,jdbcType=VARCHAR},
error_code = #{errorCode,jdbcType=VARCHAR},
match_type = #{matchType,jdbcType=VARCHAR},
`status` = #{status,jdbcType=BIT},
content = #{content,jdbcType=LONGVARCHAR},
description = #{description,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.ErrorReportLibrary">
update error_report_library
set project_id = #{projectId,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
create_user = #{createUser,jdbcType=VARCHAR},
update_user = #{updateUser,jdbcType=VARCHAR},
error_code = #{errorCode,jdbcType=VARCHAR},
match_type = #{matchType,jdbcType=VARCHAR},
`status` = #{status,jdbcType=BIT}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -0,0 +1,12 @@
package io.metersphere.commons.constants;
public enum ExecuteResult {
//误报状态
errorCode,
//接口执行状态(兼容旧数据)
success,error,
//场景执行状态(兼容旧数据)
Success,Error,
//测试计划执行状态(兼容旧数据)
PREPARE,RUNNING,SUCCESS,FAILD
}

View File

@ -177,4 +177,11 @@ public class PermissionConstants {
public static final String PROJECT_ENTERPRISE_REPORT_DELETE = "PROJECT_ENTERPRISE_REPORT:READ+DELETE"; public static final String PROJECT_ENTERPRISE_REPORT_DELETE = "PROJECT_ENTERPRISE_REPORT:READ+DELETE";
public static final String PROJECT_ENTERPRISE_REPORT_COPY = "PROJECT_ENTERPRISE_REPORT:READ+COPY"; public static final String PROJECT_ENTERPRISE_REPORT_COPY = "PROJECT_ENTERPRISE_REPORT:READ+COPY";
public static final String PROJECT_ENTERPRISE_REPORT_SCHEDULE = "PROJECT_ENTERPRISE_REPORT:READ+SCHEDULE"; public static final String PROJECT_ENTERPRISE_REPORT_SCHEDULE = "PROJECT_ENTERPRISE_REPORT:READ+SCHEDULE";
public static final String PROJECT_ERROR_REPORT_LIBRARY_EXPORT = "PROJECT_ERROR_REPORT_LIBRARY:READ+EXPORT";
public static final String PROJECT_ERROR_REPORT_LIBRARY_CREATE = "PROJECT_ERROR_REPORT_LIBRARY:READ+CREATE";
public static final String PROJECT_ERROR_REPORT_LIBRARY_EDIT = "PROJECT_ERROR_REPORT_LIBRARY:READ+EDIT";
public static final String PROJECT_ERROR_REPORT_LIBRARY_DELETE = "PROJECT_ERROR_REPORT_LIBRARY:READ+DELETE";
public static final String PROJECT_ERROR_REPORT_LIBRARY_COPY = "PROJECT_ERROR_REPORT_LIBRARY:READ+COPY";
public static final String PROJECT_ERROR_REPORT_LIBRARY_SCHEDULE = "PROJECT_ERROR_REPORT_LIBRARY:READ+SCHEDULE";
} }

View File

@ -0,0 +1,55 @@
package io.metersphere.commons.utils;
import io.metersphere.api.dto.ErrorReportLibraryParseDTO;
import io.metersphere.dto.RequestResult;
import io.metersphere.dto.ResponseAssertionResult;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
/**
* 误报解析类
*/
public class ErrorReportLibraryUtil {
private static final String ERROR_CODE_START = "Error report:";
public static ErrorReportLibraryParseDTO parseAssertions(RequestResult result) {
ErrorReportLibraryParseDTO returnDTO = new ErrorReportLibraryParseDTO();
if (result != null && result.getResponseResult() != null && CollectionUtils.isNotEmpty(result.getResponseResult().getAssertions())) {
List<ResponseAssertionResult> errorReportAssertionList = new ArrayList<>();
for (ResponseAssertionResult assertion : result.getResponseResult().getAssertions()) {
if (StringUtils.startsWith(assertion.getContent(), ERROR_CODE_START)) {
errorReportAssertionList.add(assertion);
}
}
if (CollectionUtils.isNotEmpty(errorReportAssertionList)) {
List<ResponseAssertionResult> removeList = new ArrayList<>();
for (ResponseAssertionResult assertion : errorReportAssertionList) {
if (assertion.isPass()) {
String errorCode = StringUtils.substring(assertion.getContent(), ERROR_CODE_START.length());
returnDTO.getErrorCodeList().add(errorCode);
} else {
removeList.add(assertion);
}
}
if (CollectionUtils.isNotEmpty(removeList)) {
if (result.getError() > 0) {
result.setError(result.getError() - 1);
}
result.setTotalAssertions(result.getTotalAssertions() - removeList.size());
result.getResponseResult().getAssertions().removeAll(removeList);
//修改由于误报断言导致的执行结果
if(result.getError() == 0 && !result.isSuccess()){
result.setSuccess(true);
}
}
}
}
return returnDTO;
}
}

View File

@ -3,8 +3,12 @@ package io.metersphere.commons.utils;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.RunningParamKeys; import io.metersphere.api.dto.RunningParamKeys;
import io.metersphere.api.dto.definition.request.assertions.MsAssertionRegex;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.xpack.errorreportlibrary.service.ErrorReportLibraryService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.config.Argument; import org.apache.jmeter.config.Argument;
import org.apache.jmeter.config.Arguments; import org.apache.jmeter.config.Arguments;
@ -20,135 +24,137 @@ import java.util.Map;
/** /**
* @author song.tianyang * @author song.tianyang
* 2021/7/28 3:37 下午 * 2021/7/28 3:37 下午
*/ */
public class HashTreeUtil { public class HashTreeUtil {
public Map<String,Map<String, String>> getEnvParamsDataByHashTree(HashTree hashTree, ApiTestEnvironmentService apiTestEnvironmentService){ public Map<String, Map<String, String>> getEnvParamsDataByHashTree(HashTree hashTree, ApiTestEnvironmentService apiTestEnvironmentService) {
Map<String,Map<String, String>> returnMap = new HashMap<>(); Map<String, Map<String, String>> returnMap = new HashMap<>();
Map<String, List<String>> envParamMap = this.getEnvParamsMapByHashTree(hashTree); Map<String, List<String>> envParamMap = this.getEnvParamsMapByHashTree(hashTree);
for (Map.Entry<String,List<String>> entry:envParamMap.entrySet()) { for (Map.Entry<String, List<String>> entry : envParamMap.entrySet()) {
String envId = entry.getKey(); String envId = entry.getKey();
List<String> params = entry.getValue(); List<String> params = entry.getValue();
ApiTestEnvironmentWithBLOBs environment = apiTestEnvironmentService.get(envId); ApiTestEnvironmentWithBLOBs environment = apiTestEnvironmentService.get(envId);
if(environment != null && environment.getConfig() != null){ if (environment != null && environment.getConfig() != null) {
try { try {
JSONObject configJson = JSONObject.parseObject(environment.getConfig()); JSONObject configJson = JSONObject.parseObject(environment.getConfig());
if(configJson.containsKey("commonConfig")){ if (configJson.containsKey("commonConfig")) {
JSONObject commonConfig = configJson.getJSONObject("commonConfig"); JSONObject commonConfig = configJson.getJSONObject("commonConfig");
if(commonConfig.containsKey("variables")){ if (commonConfig.containsKey("variables")) {
Map<String,String> envHeadMap = new HashMap<>(); Map<String, String> envHeadMap = new HashMap<>();
JSONArray variablesArr = commonConfig.getJSONArray("variables"); JSONArray variablesArr = commonConfig.getJSONArray("variables");
for (int i = 0; i < variablesArr.size(); i++) { for (int i = 0; i < variablesArr.size(); i++) {
JSONObject object = variablesArr.getJSONObject(i); JSONObject object = variablesArr.getJSONObject(i);
if(object.containsKey("name") && object.containsKey("value")){ if (object.containsKey("name") && object.containsKey("value")) {
boolean isEnable = true; boolean isEnable = true;
if(object.containsKey("enable")){ if (object.containsKey("enable")) {
isEnable = object.getBoolean("enable"); isEnable = object.getBoolean("enable");
} }
if(isEnable){ if (isEnable) {
envHeadMap.put(object.getString("name"),object.getString("value")); envHeadMap.put(object.getString("name"), object.getString("value"));
} }
} }
} }
for (String param :params) { for (String param : params) {
String value = envHeadMap.get(param); String value = envHeadMap.get(param);
if(value == null){ if (value == null) {
value = ""; value = "";
} }
if(returnMap.containsKey(envId)){ if (returnMap.containsKey(envId)) {
returnMap.get(envId).put(param,value); returnMap.get(envId).put(param, value);
}else { } else {
Map<String,String> map = new HashMap<>(); Map<String, String> map = new HashMap<>();
map.put(param,value); map.put(param, value);
returnMap.put(envId,map); returnMap.put(envId, map);
} }
} }
} }
} }
}catch (Exception ignored){} } catch (Exception ignored) {
}
} }
} }
return returnMap; return returnMap;
} }
public synchronized void setEnvParamsMapToHashTree(HashTree hashTree,Map<String,Map<String,String>> envParamsMap) { public synchronized void setEnvParamsMapToHashTree(HashTree hashTree, Map<String, Map<String, String>> envParamsMap) {
if(hashTree != null ){ if (hashTree != null) {
Map<String,String> allParamMap = new HashMap<>(); Map<String, String> allParamMap = new HashMap<>();
for (Map<String,String> paramMap:envParamsMap.values()) { for (Map<String, String> paramMap : envParamsMap.values()) {
allParamMap.putAll(paramMap); allParamMap.putAll(paramMap);
} }
for(Object hashTreeKey : hashTree.keySet()){ for (Object hashTreeKey : hashTree.keySet()) {
HashTree itemTree = hashTree.get(hashTreeKey); HashTree itemTree = hashTree.get(hashTreeKey);
try{ try {
if(hashTreeKey instanceof Arguments){ if (hashTreeKey instanceof Arguments) {
Arguments arguments = (Arguments)hashTreeKey; Arguments arguments = (Arguments) hashTreeKey;
List<Argument> argumentList = new ArrayList<>(); List<Argument> argumentList = new ArrayList<>();
for (int i = 0; i < arguments.getArgumentCount(); i ++){ for (int i = 0; i < arguments.getArgumentCount(); i++) {
Argument item = arguments.getArgument(i); Argument item = arguments.getArgument(i);
String name = item.getPropertyAsString("Argument.name"); String name = item.getPropertyAsString("Argument.name");
if(allParamMap.containsKey(name)){ if (allParamMap.containsKey(name)) {
item.setProperty("Argument.value",allParamMap.get(name)); item.setProperty("Argument.value", allParamMap.get(name));
} }
argumentList.add(item); argumentList.add(item);
} }
((Arguments)hashTreeKey).removeAllArguments(); ((Arguments) hashTreeKey).removeAllArguments();
for (Argument argument:argumentList) { for (Argument argument : argumentList) {
((Arguments)hashTreeKey).addArgument(argument); ((Arguments) hashTreeKey).addArgument(argument);
} }
} }
}catch (Exception ignored){ } catch (Exception ignored) {
} }
this.setEnvParamsMapToHashTree(itemTree,envParamsMap); this.setEnvParamsMapToHashTree(itemTree, envParamsMap);
} }
} }
} }
public synchronized Map<String, List<String>> getEnvParamsMapByHashTree(HashTree hashTree) { public synchronized Map<String, List<String>> getEnvParamsMapByHashTree(HashTree hashTree) {
Map<String, List<String>> returnMap = new HashMap<>(); Map<String, List<String>> returnMap = new HashMap<>();
if(hashTree != null ){ if (hashTree != null) {
for(Object hashTreeKey : hashTree.keySet()){ for (Object hashTreeKey : hashTree.keySet()) {
HashTree itemTree = hashTree.get(hashTreeKey); HashTree itemTree = hashTree.get(hashTreeKey);
String scriptValue = ""; String scriptValue = "";
try{ try {
if(hashTreeKey instanceof JSR223PostProcessor){ if (hashTreeKey instanceof JSR223PostProcessor) {
JSR223PostProcessor postProcessor = (JSR223PostProcessor)hashTreeKey; JSR223PostProcessor postProcessor = (JSR223PostProcessor) hashTreeKey;
scriptValue = postProcessor.getPropertyAsString("script"); scriptValue = postProcessor.getPropertyAsString("script");
}else if(hashTreeKey instanceof JSR223PreProcessor){ } else if (hashTreeKey instanceof JSR223PreProcessor) {
JSR223PreProcessor processor = (JSR223PreProcessor)hashTreeKey; JSR223PreProcessor processor = (JSR223PreProcessor) hashTreeKey;
scriptValue = processor.getPropertyAsString("script"); scriptValue = processor.getPropertyAsString("script");
}else if(hashTreeKey instanceof JSR223Sampler){ } else if (hashTreeKey instanceof JSR223Sampler) {
JSR223Sampler processor = (JSR223Sampler)hashTreeKey; JSR223Sampler processor = (JSR223Sampler) hashTreeKey;
scriptValue = processor.getPropertyAsString("script"); scriptValue = processor.getPropertyAsString("script");
} }
}catch (Exception ignored){ } catch (Exception ignored) {
} }
if(StringUtils.isNotEmpty(scriptValue)){ if (StringUtils.isNotEmpty(scriptValue)) {
if(scriptValue.contains(RunningParamKeys.RUNNING_PARAMS_PREFIX)){ if (scriptValue.contains(RunningParamKeys.RUNNING_PARAMS_PREFIX)) {
String [] paramsArr = scriptValue.split(RunningParamKeys.RUNNING_PARAMS_PREFIX); String[] paramsArr = scriptValue.split(RunningParamKeys.RUNNING_PARAMS_PREFIX);
for(int i = 1; i < paramsArr.length;i++){ for (int i = 1; i < paramsArr.length; i++) {
String paramItem = paramsArr[i]; String paramItem = paramsArr[i];
if(StringUtils.contains(paramItem,".")){ if (StringUtils.contains(paramItem, ".")) {
String envId = paramItem.split("\\.")[0]; String envId = paramItem.split("\\.")[0];
String otherStr = paramItem.substring(envId.length()+3); String otherStr = paramItem.substring(envId.length() + 3);
String firstChar = otherStr.substring(0,1); String firstChar = otherStr.substring(0, 1);
String [] envParamsStr = otherStr.split(firstChar); String[] envParamsStr = otherStr.split(firstChar);
if(envParamsStr.length > 1){ if (envParamsStr.length > 1) {
String param = envParamsStr[1]; String param = envParamsStr[1];
if(returnMap.containsKey(envId)){ if (returnMap.containsKey(envId)) {
returnMap.get(envId).add(param); returnMap.get(envId).add(param);
}else { } else {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
list.add(param); list.add(param);
returnMap.put(envId,list); returnMap.put(envId, list);
} }
} }
} }
@ -158,18 +164,18 @@ public class HashTreeUtil {
Map<String, List<String>> itemMap = this.getEnvParamsMapByHashTree(itemTree); Map<String, List<String>> itemMap = this.getEnvParamsMapByHashTree(itemTree);
for (Map.Entry<String,List<String>> entry:itemMap.entrySet()) { for (Map.Entry<String, List<String>> entry : itemMap.entrySet()) {
String envId = entry.getKey(); String envId = entry.getKey();
List<String> params = entry.getValue(); List<String> params = entry.getValue();
if(returnMap.containsKey(envId)){ if (returnMap.containsKey(envId)) {
for (String param:params) { for (String param : params) {
if(!returnMap.get(envId).contains(param)){ if (!returnMap.get(envId).contains(param)) {
returnMap.get(envId).add(param); returnMap.get(envId).add(param);
} }
} }
}else { } else {
returnMap.put(envId,params); returnMap.put(envId, params);
} }
} }
} }
@ -178,21 +184,57 @@ public class HashTreeUtil {
} }
public Map<String, Map<String, String>> mergeParamDataMap(Map<String, Map<String, String>> execute_env_param_dataMap, Map<String, Map<String, String>> envParamsMap) { public Map<String, Map<String, String>> mergeParamDataMap(Map<String, Map<String, String>> execute_env_param_dataMap, Map<String, Map<String, String>> envParamsMap) {
if(execute_env_param_dataMap == null){ if (execute_env_param_dataMap == null) {
execute_env_param_dataMap = new HashMap<>(); execute_env_param_dataMap = new HashMap<>();
} }
if(envParamsMap == null){ if (envParamsMap == null) {
return execute_env_param_dataMap; return execute_env_param_dataMap;
} }
for (Map.Entry<String,Map<String,String>> paramEnvMapEntry:envParamsMap.entrySet()) { for (Map.Entry<String, Map<String, String>> paramEnvMapEntry : envParamsMap.entrySet()) {
String envId = paramEnvMapEntry.getKey(); String envId = paramEnvMapEntry.getKey();
Map<String,String> map = paramEnvMapEntry.getValue(); Map<String, String> map = paramEnvMapEntry.getValue();
if(execute_env_param_dataMap.containsKey(envId)){ if (execute_env_param_dataMap.containsKey(envId)) {
execute_env_param_dataMap.get(envId).putAll(map); execute_env_param_dataMap.get(envId).putAll(map);
}else { } else {
execute_env_param_dataMap.put(envId,map); execute_env_param_dataMap.put(envId, map);
} }
} }
return execute_env_param_dataMap; return execute_env_param_dataMap;
} }
public MsAssertions duplicateRegexInAssertions(List<MsAssertions> compareList, MsAssertions target) {
if (target != null && CollectionUtils.isNotEmpty(target.getRegex())) {
List<MsAssertionRegex> compareRegexList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(compareList)) {
for (MsAssertions assertions : compareList) {
if (assertions != null && CollectionUtils.isNotEmpty(assertions.getRegex())) {
compareRegexList.addAll(assertions.getRegex());
}
}
}
List<MsAssertionRegex> duplicatedList = new ArrayList<>();
for (MsAssertionRegex regex : target.getRegex()) {
boolean isExit = false;
for (MsAssertionRegex compareRegex : compareRegexList) {
if (StringUtils.equals(regex.getType(), compareRegex.getType())
&& StringUtils.equals(regex.getSubject(), compareRegex.getSubject())
&& StringUtils.equals(regex.getExpression(), compareRegex.getExpression())) {
isExit = true;
break;
}
}
if(!isExit){
duplicatedList.add(regex);
}
}
target.setRegex(duplicatedList);
}
return target;
}
public static List<MsAssertions> getErrorReportByProjectId(String projectId) {
ErrorReportLibraryService service = CommonBeanFactory.getBean(ErrorReportLibraryService.class);
return service.getAssertionByProjectIdAndStatusIsOpen(projectId);
}
} }

View File

@ -0,0 +1,19 @@
package io.metersphere.log.vo.errorreportlibrary;
import java.util.LinkedHashMap;
import java.util.Map;
public class ErrorReportLibraryReference {
public static Map<String, String> errorReportLibraryColumns = new LinkedHashMap<>();
static {
errorReportLibraryColumns.clear();
errorReportLibraryColumns.put("errorCode", "错误码");
errorReportLibraryColumns.put("matchType", "匹配规则");
errorReportLibraryColumns.put("createUser", "创建人");
errorReportLibraryColumns.put("updateUser", "修改人");
errorReportLibraryColumns.put("status", "启用状态");
errorReportLibraryColumns.put("description", "描述");
errorReportLibraryColumns.put("content", "断言规则");
}
}

@ -1 +1 @@
Subproject commit 2b282af4570ee24c8bb61edd7a07271974534737 Subproject commit a8c5c8445fac63ece0e2c6582d2530eec702c0dc

View File

@ -292,4 +292,7 @@ enterprise_test_report=Enterprise report
null_environment_group_name = Environment group name is null null_environment_group_name = Environment group name is null
environment_group_name = Environment group name environment_group_name = Environment group name
environment_group_exist = already exists environment_group_exist = already exists
#误报库
error_report_library=Error report
issue_jira_info_error=Check the service integration information or Jira project ID issue_jira_info_error=Check the service integration information or Jira project ID
error_code_is_unique=Error code is not unique

View File

@ -291,4 +291,7 @@ enterprise_test_report=项目报告
null_environment_group_name = 环境组名称不存在 null_environment_group_name = 环境组名称不存在
environment_group_name = 环境组名称 environment_group_name = 环境组名称
environment_group_exist = 已存在 environment_group_exist = 已存在
#误报库
error_report_library=误报库
issue_jira_info_error=请检查服务集成信息或Jira项目ID issue_jira_info_error=请检查服务集成信息或Jira项目ID
error_code_is_unique=错误代码不可重复

View File

@ -291,4 +291,7 @@ enterprise_test_report=項目報告
null_environment_group_name = 環境組名稱不存在 null_environment_group_name = 環境組名稱不存在
environment_group_name = 環境組名稱 environment_group_name = 環境組名稱
environment_group_exist = 已存在 environment_group_exist = 已存在
#误报库
error_report_library=誤報庫
issue_jira_info_error=請檢查服務集成信息或Jira項目ID issue_jira_info_error=請檢查服務集成信息或Jira項目ID
error_code_is_unique=錯誤代碼不可重複

View File

@ -919,6 +919,30 @@
"name": "project.version.enable", "name": "project.version.enable",
"resourceId": "PROJECT_VERSION", "resourceId": "PROJECT_VERSION",
"license": true "license": true
},
{
"id": "PROJECT_ERROR_REPORT_LIBRARY:READ",
"name": "permission.project_error_report_library.read",
"resourceId": "PROJECT_ERROR_REPORT_LIBRARY",
"license": true
},
{
"id": "PROJECT_ERROR_REPORT_LIBRARY:READ+CREATE",
"name": "permission.project_error_report_library.create",
"resourceId": "PROJECT_ERROR_REPORT_LIBRARY",
"license": true
},
{
"id": "PROJECT_ERROR_REPORT_LIBRARY:READ+EDIT",
"name": "permission.project_error_report_library.edit",
"resourceId": "PROJECT_ERROR_REPORT_LIBRARY",
"license": true
},
{
"id": "PROJECT_ERROR_REPORT_LIBRARY:READ+DELETE",
"name": "permission.project_error_report_library.delete",
"resourceId": "PROJECT_ERROR_REPORT_LIBRARY",
"license": true
} }
], ],
"resource": [ "resource": [
@ -1071,6 +1095,11 @@
{ {
"id": "SYSTEM_PLUGIN", "id": "SYSTEM_PLUGIN",
"name": "permission.system_plugin.name" "name": "permission.system_plugin.name"
},
{
"id": "PROJECT_ERROR_REPORT_LIBRARY",
"name": "permission.project_error_report_library.name",
"license": true
} }
] ]
} }

View File

@ -3,25 +3,30 @@
<ms-main-container> <ms-main-container>
<el-card> <el-card>
<section class="report-container" v-if="this.report.testId"> <section class="report-container" v-if="this.report.testId">
<ms-api-report-view-header :show-cancel-button="showCancelButton" :is-plan="isPlan" :is-template="isTemplate" :debug="debug" :report="report" @reportExport="handleExport" @reportSave="handleSave"/> <ms-api-report-view-header :show-cancel-button="showCancelButton" :is-plan="isPlan" :is-template="isTemplate"
:debug="debug" :report="report" @reportExport="handleExport"
@reportSave="handleSave"/>
<main v-if="isNotRunning"> <main v-if="isNotRunning">
<ms-metric-chart :content="content" :totalTime="totalTime"/> <ms-metric-chart :content="content" :totalTime="totalTime"/>
<div> <div>
<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane :label="$t('api_report.total')" name="total"> <el-tab-pane :label="$t('api_report.total')" name="total">
<ms-scenario-results :treeData="fullTreeNodes" :console="content.console" v-on:requestResult="requestResult" ref="resultsTree"/> <ms-scenario-results :treeData="fullTreeNodes" :console="content.console"
v-on:requestResult="requestResult" ref="resultsTree"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane name="fail"> <el-tab-pane name="fail">
<template slot="label"> <template slot="label">
<span class="fail">{{ $t('api_report.fail') }}</span> <span class="fail">{{ $t('api_report.fail') }}</span>
</template> </template>
<ms-scenario-results v-on:requestResult="requestResult" :console="content.console" :treeData="fullTreeNodes" ref="failsTree"/> <ms-scenario-results v-on:requestResult="requestResult" :console="content.console"
:treeData="fullTreeNodes" ref="failsTree"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane name="console"> <el-tab-pane name="console">
<template slot="label"> <template slot="label">
<span class="console">{{ $t('api_test.definition.request.console') }}</span> <span class="console">{{ $t('api_test.definition.request.console') }}</span>
</template> </template>
<ms-code-edit :mode="'text'" :read-only="true" :data.sync="content.console" height="calc(100vh - 500px)"/> <ms-code-edit :mode="'text'" :read-only="true" :data.sync="content.console"
height="calc(100vh - 500px)"/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
@ -334,7 +339,7 @@ export default {
this.fullTreeNodes = report.steps; this.fullTreeNodes = report.steps;
this.content.console = report.console; this.content.console = report.console;
this.content.error = report.error; this.content.error = report.error;
this.content.success = (report.total - report.error); this.content.success = (report.total - report.error - report.errorCode);
this.totalTime = report.totalTime; this.totalTime = report.totalTime;
} }
this.loading = false; this.loading = false;
@ -418,7 +423,7 @@ export default {
requestTime = requestTime + resTime; requestTime = requestTime + resTime;
}) })
}) })
this.totalTime = requestTime this.totalTime = requestTime
} }
}, },
requestResult(requestResult) { requestResult(requestResult) {

View File

@ -277,10 +277,11 @@ export default {
this.content = {scenarios: []}; this.content = {scenarios: []};
} }
this.content.error = this.content.error; this.content.error = this.content.error;
this.content.success = (this.content.total - this.content.error); this.content.success = (this.content.total - this.content.error - this.content.errorCode);
this.totalTime = this.content.totalTime; this.totalTime = this.content.totalTime;
this.fullTreeNodes = JSON.parse(JSON.stringify(this.fullTreeNodes)); this.fullTreeNodes = this.content.steps;
this.recursiveSorting(this.fullTreeNodes); this.recursiveSorting(this.fullTreeNodes);
console.info(this.fullTreeNodes);
this.reload(); this.reload();
} }
}); });

View File

@ -19,16 +19,30 @@
</div> </div>
<ms-chart id="chart" ref="chart" :options="options" :height="220" :autoresize="true" v-else/> <ms-chart id="chart" ref="chart" :options="options" :height="220" :autoresize="true" v-else/>
<el-row type="flex" justify="center" align="middle"> <el-row type="flex" justify="center" align="middle">
<span class="ms-point-success"/>
<div class="metric-box"> <div>
<div class="value">{{ content.success }}</div> <div class="metric-icon-box" style="height: 26px">
<div class="name">{{ $t('api_report.success') }}</div> <span class="ms-point-success" style="margin: 7px"/>
</div> <div class="metric-box">
<span class="ms-point-error"/> <div class="value">{{ content.success }} {{ $t('api_report.success') }}</div>
<div class="metric-box"> </div>
<div class="value">{{ content.error }}</div> </div>
<div class="name">{{ $t('api_report.fail') }}</div> <el-divider></el-divider>
<div class="metric-icon-box" style="height: 26px">
<span class="ms-point-error" style="margin: 7px"/>
<div class="metric-box">
<div class="value">{{ content.error }} {{ $t('api_report.fail') }}</div>
</div>
</div>
<el-divider v-if="content.errorCode > 0"></el-divider>
<div class="metric-icon-box" style="height: 26px">
<span class="ms-point-error-code" v-if="content.errorCode > 0" style="margin: 7px"/>
<div class="metric-box" v-if="content.errorCode > 0">
<div class="value">{{ content.errorCode }} {{ $t('error_report_library.option.name') }}</div>
</div>
</div>
</div> </div>
</el-row> </el-row>
</el-row> </el-row>
</div> </div>
@ -36,24 +50,25 @@
<!-- 场景统计 --> <!-- 场景统计 -->
<div style="width: 50%"> <div style="width: 50%">
<el-row type="flex" justify="center" align="middle"> <el-row type="flex" justify="center" align="middle">
<!-- <div class="metric-box" style="margin-right: 50px">-->
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioTotal ? content.scenarioTotal : 0}}</div> <div class="value">{{ content.scenarioTotal ? content.scenarioTotal : 0}}</div>
<div class="name">{{ $t('api_test.scenario.scenario') }}</div> <div class="name">{{ $t('api_test.scenario.scenario') }}</div>
</div> </div>
<!-- <i class="circle success" style="margin-left: 20px;margin-right: 20px"/>-->
<span class="ms-point-success"/> <span class="ms-point-success"/>
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioSuccess ? content.scenarioSuccess: 0 }}</div> <div class="value">{{ content.scenarioSuccess ? content.scenarioSuccess: 0 }}</div>
<div class="name">{{ $t('api_report.success') }}</div> <div class="name">{{ $t('api_report.success') }}</div>
</div> </div>
<!-- <div style="width: 40px"></div>-->
<!-- <i class="circle fail" style="margin-left: 20px;margin-right: 20px"/>-->
<span class="ms-point-error"/> <span class="ms-point-error"/>
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioError ? content.scenarioError : 0 }}</div> <div class="value">{{ content.scenarioError ? content.scenarioError : 0 }}</div>
<div class="name">{{ $t('api_report.fail') }}</div> <div class="name">{{ $t('api_report.fail') }}</div>
</div> </div>
<span class="ms-point-error-code" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 "/>
<div class="metric-box" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 ">
<div class="value">{{ content.scenarioErrorReport ? content.scenarioErrorReport : 0 }}</div>
<div class="name">{{ $t('error_report_library.option.name') }}</div>
</div>
</el-row> </el-row>
<el-divider></el-divider> <el-divider></el-divider>
<el-row type="flex" justify="center" align="middle"> <el-row type="flex" justify="center" align="middle">
@ -63,18 +78,20 @@
<div class="name">{{ $t('test_track.plan_view.step') }}</div> <div class="name">{{ $t('test_track.plan_view.step') }}</div>
</div> </div>
<span class="ms-point-success"/> <span class="ms-point-success"/>
<!-- <i class="circle success" style="margin-left: 20px;margin-right: 20px"/>-->
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioStepSuccess ? content.scenarioStepSuccess: 0 }}</div> <div class="value">{{ content.scenarioStepSuccess ? content.scenarioStepSuccess: 0 }}</div>
<div class="name">{{ $t('api_report.success') }}</div> <div class="name">{{ $t('api_report.success') }}</div>
</div> </div>
<!-- <div style="width: 40px"></div>-->
<!-- <i class="circle fail" style="margin-left: 20px;margin-right: 20px"/>-->
<span class="ms-point-error"/> <span class="ms-point-error"/>
<div class="metric-box"> <div class="metric-box">
<div class="value">{{ content.scenarioStepError ? content.scenarioStepError : 0 }}</div> <div class="value">{{ content.scenarioStepError ? content.scenarioStepError : 0 }}</div>
<div class="name">{{ $t('api_report.fail') }}</div> <div class="name">{{ $t('api_report.fail') }}</div>
</div> </div>
<span class="ms-point-error-code" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 "/>
<div class="metric-box" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 ">
<div class="value">{{ content.scenarioStepErrorReport ? content.scenarioStepErrorReport : 0 }}</div>
<div class="name">{{ $t('error_report_library.option.name') }}</div>
</div>
</el-row> </el-row>
</el-row> </el-row>
</div> </div>
@ -92,6 +109,11 @@
<div class="value">{{ assertions }}</div> <div class="value">{{ assertions }}</div>
<div class="name">{{ $t('api_report.assertions_pass') }}</div> <div class="name">{{ $t('api_report.assertions_pass') }}</div>
</div> </div>
<div class="metric-icon-box" v-if="content.errorCode > 0">
<i class="el-icon-document-checked assertions"></i>
<div class="value">{{ errorCodeAssertions }}</div>
<div class="name">{{ $t('error_report_library.assertion') }}</div>
</div>
<div class="metric-icon-box"> <div class="metric-icon-box">
<i class="el-icon-document-copy total"></i> <i class="el-icon-document-copy total"></i>
<div class="value">{{ this.content.total }}</div> <div class="value">{{ this.content.total }}</div>
@ -160,7 +182,7 @@
computed: { computed: {
options() { options() {
return { return {
color: ['#67C23A', '#F56C6C'], color: ['#67C23A', '#F56C6C' ,'#F6972A'],
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
formatter: '{b}: {c} ({d}%)' formatter: '{b}: {c} ({d}%)'
@ -203,6 +225,7 @@
data: [ data: [
{value: this.content.success}, {value: this.content.success},
{value: this.content.error}, {value: this.content.error},
{value: this.content.errorCode},
] ]
} }
] ]
@ -214,6 +237,9 @@
}, },
assertions() { assertions() {
return this.content.passAssertions + " / " + this.content.totalAssertions; return this.content.passAssertions + " / " + this.content.totalAssertions;
},
errorCodeAssertions() {
return this.content.errorCode + " / " + this.content.totalAssertions;
} }
}, },
} }
@ -355,4 +381,15 @@
margin-right: 20px; margin-right: 20px;
background-color : #F56C6C; background-color : #F56C6C;
} }
.ms-point-error-code {
border-radius: 50%;
height: 12px;
width: 12px;
display: inline-block;
vertical-align: top;
margin-left: 20px;
margin-right: 20px;
background-color : #F6972A;
}
</style> </style>

View File

@ -1,7 +1,7 @@
<template> <template>
<el-card class="ms-cards" v-if="request && request.responseResult"> <el-card class="ms-cards" v-if="request && request.responseResult">
<div class="request-result"> <div class="request-result">
<div @click="active" > <div @click="active">
<el-row :gutter="10" type="flex" align="middle" class="info"> <el-row :gutter="10" type="flex" align="middle" class="info">
<el-col :span="10" v-if="indexNumber!=undefined"> <el-col :span="10" v-if="indexNumber!=undefined">
<el-tooltip :content="getName(request.name)" placement="top"> <el-tooltip :content="getName(request.name)" placement="top">
@ -14,8 +14,19 @@
</div> </div>
</el-tooltip> </el-tooltip>
</el-col> </el-col>
<el-col :span="9"> <el-col :span="3">
<el-tooltip effect="dark" :content="request.responseResult.responseCode" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom" :open-delay="800"> <el-tooltip effect="dark" v-if="errorCode" :content="errorCode"
style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom"
:open-delay="800">
<div style="color: #F6972A">
{{ errorCode }}
</div>
</el-tooltip>
</el-col>
<el-col :span="6">
<el-tooltip effect="dark" :content="request.responseResult.responseCode"
style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom"
:open-delay="800">
<div style="color: #5daf34" v-if="request.success"> <div style="color: #5daf34" v-if="request.success">
{{ request.responseResult.responseCode }} {{ request.responseResult.responseCode }}
</div> </div>
@ -35,10 +46,16 @@
<el-col :span="2"> <el-col :span="2">
<div> <div>
<el-tag v-if="request.testing" class="ms-test-running" size="mini"> <el-tag v-if="request.testing" class="ms-test-running" size="mini">
<i class="el-icon-loading" style="font-size: 16px"/> <i class="el-icon-loading" style="font-size: 16px"/>
{{ $t('commons.testing') }} {{ $t('commons.testing') }}
</el-tag> </el-tag>
<el-tag size="mini" v-else-if="request.unexecute">{{ $t('api_test.home_page.detail_card.unexecute') }}</el-tag> <el-tag v-if="errorCode" class="ms-test-running" size="mini">
{{ $t('error_report_library.option.name') }}
</el-tag>
<el-tag size="mini" v-else-if="request.unexecute">{{
$t('api_test.home_page.detail_card.unexecute')
}}
</el-tag>
<el-tag size="mini" type="success" v-else-if="request.success"> {{ $t('api_report.success') }}</el-tag> <el-tag size="mini" type="success" v-else-if="request.success"> {{ $t('api_report.success') }}</el-tag>
<el-tag size="mini" type="danger" v-else> {{ $t('api_report.fail') }}</el-tag> <el-tag size="mini" type="danger" v-else> {{ $t('api_report.fail') }}</el-tag>
</div> </div>
@ -49,11 +66,11 @@
<el-collapse-transition> <el-collapse-transition>
<div v-show="isActive && !request.unexecute" style="width: 99%"> <div v-show="isActive && !request.unexecute" style="width: 99%">
<ms-request-result-tail <ms-request-result-tail
:scenario-name="scenarioName" :scenario-name="scenarioName"
:request-type="requestType" :request-type="requestType"
:request="request" :request="request"
:console="console" :console="console"
v-if="isActive"/> v-if="isActive"/>
</div> </div>
</el-collapse-transition> </el-collapse-transition>
</div> </div>
@ -81,6 +98,7 @@ export default {
scenarioName: String, scenarioName: String,
indexNumber: Number, indexNumber: Number,
console: String, console: String,
errorCode: String,
}, },
data() { data() {
return { return {
@ -100,6 +118,8 @@ export default {
}, },
} }
}, },
created() {
},
methods: { methods: {
active() { active() {
if (this.request.unexecute) { if (this.request.unexecute) {

View File

@ -9,7 +9,7 @@
</el-card> </el-card>
</div> </div>
<div v-else> <div v-else>
<ms-request-result :request="node.value" :indexNumber="node.index" <ms-request-result :request="node.value" :indexNumber="node.index" :error-code="node.errorCode"
v-on:requestResult="requestResult" v-on:requestResult="requestResult"
:scenarioName="node.label" :console="console"/> :scenarioName="node.label" :console="console"/>
</div> </div>

View File

@ -0,0 +1,128 @@
<template>
<div>
<el-row :gutter="10" type="flex" justify="space-between" align="middle">
<el-col class="assertion-select">
<el-select :disabled="isReadOnly" class="assertion-item" v-model="subject" size="small"
:placeholder="$t('api_test.request.assertions.select_subject')">
<el-option label="Response Code" :value="subjects.RESPONSE_CODE"/>
<el-option label="Response Headers" :value="subjects.RESPONSE_HEADERS"/>
<el-option label="Response Data" :value="subjects.RESPONSE_DATA"/>
</el-select>
</el-col>
<el-col class="assertion-select">
<el-select :disabled="isReadOnly" class="assertion-item" v-model="condition" size="small"
:placeholder="$t('api_test.request.assertions.select_condition')">
<el-option :label="$t('api_test.request.assertions.contains')" value="CONTAINS"/>
<el-option :label="$t('api_test.request.assertions.not_contains')" value="NOT_CONTAINS"/>
<el-option :label="$t('api_test.request.assertions.equals')" value="EQUALS"/>
<el-option :label="$t('api_test.request.assertions.start_with')" value="START_WITH"/>
<el-option :label="$t('api_test.request.assertions.end_with')" value="END_WITH"/>
</el-select>
</el-col>
<el-col>
<el-input :disabled="isReadOnly" v-model="value" maxlength="200" size="small" show-word-limit
:placeholder="$t('api_test.request.assertions.value')"/>
</el-col>
<el-col class="assertion-checkbox">
<el-checkbox v-model="assumeSuccess" :disabled="isReadOnly">
{{ $t('api_test.request.assertions.ignore_status') }}
</el-checkbox>
</el-col>
<el-col class="assertion-btn">
<el-button :disabled="isReadOnly" v-if="showAddButton" type="primary" size="small" @click="add">
{{ $t('api_test.request.assertions.add') }}
</el-button>
</el-col>
</el-row>
</div>
</template>
<script>
import {Regex, ASSERTION_REGEX_SUBJECT} from "../../model/ApiTestModel";
export default {
name: "MsApiAssertionText",
props: {
list: Array,
callback: Function,
isReadOnly: {
type: Boolean,
default: false
},
showAddButton: {
type: Boolean,
default: true
}
},
data() {
return {
subjects: ASSERTION_REGEX_SUBJECT,
subject: "",
condition: "",
assumeSuccess: false,
value: ""
}
},
methods: {
add: function () {
this.list.push(this.toRegex());
this.callback();
},
toRegex: function () {
let expression = "";
let description = this.subject;
switch (this.condition) {
case "CONTAINS":
expression = ".*" + this.value + ".*";
description += " contains: " + this.value;
break;
case "NOT_CONTAINS":
expression = "(?s)^((?!" + this.value + ").)*$";
description += " not contains: " + this.value;
break;
case "EQUALS":
expression = "^" + this.value + "$";
description += " equals: " + this.value;
break;
case "START_WITH":
expression = "^" + this.value;
description += " start with: " + this.value;
break;
case "END_WITH":
expression = this.value + "$";
description += " end with: " + this.value;
break;
}
return new Regex({
subject: this.subject,
expression: expression,
description: description,
assumeSuccess: this.assumeSuccess
}
);
}
}
}
</script>
<style scoped>
.assertion-select {
width: 250px;
}
.assertion-item {
width: 100%;
}
.assertion-checkbox {
text-align: center;
width: 120px;
}
.assertion-btn {
width: 60px;
}
</style>

View File

@ -0,0 +1,233 @@
<template>
<div>
<div class="assertion-add" :draggable="draggable">
<el-row :gutter="10">
<el-col :span="4">
<el-select :disabled="isReadOnly" class="assertion-item" v-model="type"
:placeholder="$t('api_test.request.assertions.select_type')" size="small">
<el-option :label="$t('api_test.request.assertions.text')" :value="options.TEXT"/>
<el-option :label="$t('api_test.request.assertions.regex')" :value="options.REGEX"/>
<el-option :label="'JSONPath'" :value="options.JSON_PATH"/>
<el-option :label="'XPath'" :value="options.XPATH2"/>
<el-option :label="$t('api_test.request.assertions.response_time')" :value="options.DURATION"/>
<el-option :label="$t('api_test.request.assertions.jsr223')" :value="options.JSR223"/>
<el-option :label="$t('api_test.definition.request.document_structure')" :value="options.DOCUMENT"/>
</el-select>
</el-col>
<el-col :span="20">
<global-assertion-text
:is-read-only="isReadOnly"
:list="assertions.regex"
:callback="after"
v-if="type === options.TEXT"
/>
<ms-api-assertion-regex
:is-read-only="isReadOnly"
:list="assertions.regex"
:callback="after"
v-if="type === options.REGEX"
/>
<ms-api-assertion-json-path
:is-read-only="isReadOnly"
:list="assertions.jsonPath"
:callback="after"
v-if="type === options.JSON_PATH"
/>
<ms-api-assertion-x-path2
:is-read-only="isReadOnly"
:list="assertions.xpath2"
:callback="after"
v-if="type === options.XPATH2"
/>
<ms-api-assertion-duration
v-model="time"
:is-read-only="isReadOnly"
:duration="assertions.duration"
:callback="after"
v-if="type === options.DURATION"
/>
<ms-api-assertion-jsr223
:is-read-only="isReadOnly"
:list="assertions.jsr223"
:callback="after"
v-if="type === options.JSR223"
/>
<ms-api-assertion-document
:is-read-only="isReadOnly"
v-model="time"
:document="assertions.document"
:callback="after"
v-if="type === options.DOCUMENT"
/>
<el-button v-if="!type" :disabled="true" type="primary" size="small">
{{ $t('api_test.request.assertions.add') }}
</el-button>
</el-col>
</el-row>
</div>
<api-json-path-suggest-button
:open-tip="$t('api_test.request.assertions.json_path_suggest')"
:clear-tip="$t('api_test.request.assertions.json_path_clear')"
@open="suggestJsonOpen"
@clear="clearJson"/>
<ms-api-assertions-edit
:is-read-only="isReadOnly"
:assertions="assertions"
:apiId="apiId"
:reloadData="reloadData"
style="margin-bottom: 20px"/>
<api-jsonpath-suggest
:tip="$t('api_test.request.extract.suggest_tip')"
@addSuggest="addJsonPathSuggest"
ref="jsonpathSuggest"/>
</div>
</template>
<script>
import GlobalAssertionText from "@/business/components/api/definition/components/assertion/GlobalAssertionText";
import MsApiAssertionRegex from "@/business/components/api/definition/components/assertion/ApiAssertionRegex";
import MsApiAssertionDuration from "@/business/components/api/definition/components/assertion/ApiAssertionDuration";
import {ASSERTION_TYPE, JSONPath} from "@/business/components/api/definition/model/ApiTestModel";
import MsApiAssertionsEdit from "@/business/components/api/definition/components/assertion/ApiAssertionsEdit";
import MsApiAssertionJsonPath from "@/business/components/api/definition/components/assertion/ApiAssertionJsonPath";
import MsApiAssertionJsr223 from "@/business/components/api/definition/components/assertion/ApiAssertionJsr223";
import MsApiJsonpathSuggestList from "@/business/components/api/definition/components/assertion/ApiJsonpathSuggestList";
import MsApiAssertionXPath2 from "@/business/components/api/definition/components/assertion/ApiAssertionXPath2";
import {getUUID} from "@/common/js/utils";
import ApiJsonPathSuggestButton
from "@/business/components/api/definition/components/assertion/ApiJsonPathSuggestButton";
import ApiJsonpathSuggest from "@/business/components/api/definition/components/assertion/ApiJsonpathSuggest";
import ApiBaseComponent from "@/business/components/api/automation/scenario/common/ApiBaseComponent";
import MsApiAssertionDocument from "@/business/components/api/definition/components/assertion/document/DocumentHeader";
export default {
name: "GlobalAssertions",
components: {
ApiBaseComponent,
ApiJsonpathSuggest,
ApiJsonPathSuggestButton,
MsApiAssertionXPath2,
MsApiAssertionJsr223,
MsApiJsonpathSuggestList,
MsApiAssertionJsonPath,
MsApiAssertionsEdit,
MsApiAssertionDuration,
MsApiAssertionRegex,
GlobalAssertionText,
MsApiAssertionDocument,
},
props: {
draggable: {
type: Boolean,
default: false,
},
isMax: {
type: Boolean,
default: false,
},
showBtn: {
type: Boolean,
default: true,
},
assertions: {},
node: {},
request: {},
apiId: String,
response: {},
customizeStyle: {
type: String,
default: "margin-top: 10px"
},
isReadOnly: {
type: Boolean,
default: false
}
},
data() {
return {
options: ASSERTION_TYPE,
time: "",
type: "",
loading: false,
reloadData: "",
}
},
created() {
},
methods: {
after() {
this.type = "";
this.reloadData = getUUID().substring(0, 8);
this.reload();
},
copyRow() {
this.$emit('copyRow', this.assertions, this.node);
},
suggestJsonOpen() {
this.$emit('suggestClick');
this.$nextTick(() => {
if (!this.response || !this.response.responseResult || !this.response.responseResult.body) {
this.$message(this.$t('api_test.request.assertions.debug_first'));
return;
}
this.$refs.jsonpathSuggest.open(this.response.responseResult.body);
})
},
reload() {
this.loading = true
this.$nextTick(() => {
this.loading = false
})
},
active() {
this.assertions.active = !this.assertions.active;
this.reload();
},
remove() {
this.$emit('remove', this.assertions, this.node);
},
addJsonPathSuggest(data) {
let jsonItem = new JSONPath();
jsonItem.expression = data.path;
jsonItem.expect = data.value;
jsonItem.setJSONPathDescription();
let expect = jsonItem.expect;
if (expect) {
expect = expect.replaceAll('\\', "\\\\").replaceAll('(', "\\(").replaceAll(')', "\\)")
.replaceAll('+', "\\+").replaceAll('.', "\\.").replaceAll('[', "\\[").replaceAll(']', "\\]")
.replaceAll('?', "\\?").replaceAll('/', "\\/").replaceAll('*', "\\*")
.replaceAll('^', "\\^").replaceAll('{', "\\{").replaceAll('}', "\\}").replaceAll('$', "\\$");
}
jsonItem.expect = expect;
this.assertions.jsonPath.push(jsonItem);
},
clearJson() {
this.assertions.jsonPath = [];
}
}
}
</script>
<style scoped>
.assertion-item {
width: 100%;
}
.assertion-add {
padding: 10px;
margin: 5px 0;
border-radius: 5px;
border: #DCDFE6 solid 1px;
}
.icon.is-active {
transform: rotate(90deg);
}
/deep/ .el-card__body {
padding: 6px 10px;
}
</style>

View File

@ -3,18 +3,21 @@
<el-form :model="environment" :rules="rules" ref="environment" label-width="80px"> <el-form :model="environment" :rules="rules" ref="environment" label-width="80px">
<el-form-item prop="name" :label="$t('api_test.environment.name')"> <el-form-item prop="name" :label="$t('api_test.environment.name')">
<el-input v-model="environment.name" :disabled="isReadOnly" :placeholder="this.$t('commons.input_name')" clearable/> <el-input v-model="environment.name" :disabled="isReadOnly" :placeholder="this.$t('commons.input_name')"
clearable/>
</el-form-item> </el-form-item>
<el-tabs v-model="activeName"> <el-tabs v-model="activeName">
<el-tab-pane :label="$t('api_test.environment.common_config')" name="common"> <el-tab-pane :label="$t('api_test.environment.common_config')" name="common">
<ms-environment-common-config :common-config="environment.config.commonConfig" ref="commonConfig" :is-read-only="isReadOnly"/> <ms-environment-common-config :common-config="environment.config.commonConfig" ref="commonConfig"
:is-read-only="isReadOnly"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.environment.http_config')" name="http"> <el-tab-pane :label="$t('api_test.environment.http_config')" name="http">
<ms-environment-http-config :project-id="projectId" :http-config="environment.config.httpConfig" ref="httpConfig" :is-read-only="isReadOnly"/> <ms-environment-http-config :project-id="projectId" :http-config="environment.config.httpConfig"
ref="httpConfig" :is-read-only="isReadOnly"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.environment.database_config')" name="sql"> <el-tab-pane :label="$t('api_test.environment.database_config')" name="sql">
<ms-database-config :configs="environment.config.databaseConfigs" :is-read-only="isReadOnly"/> <ms-database-config :configs="environment.config.databaseConfigs" :is-read-only="isReadOnly"/>
@ -23,59 +26,57 @@
<ms-tcp-config :config="environment.config.tcpConfig" :is-read-only="isReadOnly"/> <ms-tcp-config :config="environment.config.tcpConfig" :is-read-only="isReadOnly"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('commons.ssl.config')" name="ssl"> <el-tab-pane :label="$t('commons.ssl.config')" name="ssl">
<ms-environment-s-s-l-config :project-id="projectId" :ssl-config="environment.config.sslConfig" :is-read-only="isReadOnly"/> <ms-environment-s-s-l-config :project-id="projectId" :ssl-config="environment.config.sslConfig"
:is-read-only="isReadOnly"/>
</el-tab-pane> </el-tab-pane>
<!-- <el-tab-pane :label="$t('api_test.definition.request.all_pre_script')" name="prescript">-->
<!-- <el-switch v-model="environment.config.preProcessor.connScenario" active-text="关联场景结果"-->
<!-- style="margin: 5px 5px 5px 5px"/>-->
<!-- <el-tooltip class="item" effect="dark" content="脚本步骤会统计到场景执行结果中,执行报错时会影响场景的最终执行结果" placement="right">-->
<!-- <i class="el-icon-info"/>-->
<!-- </el-tooltip>-->
<!-- <jsr233-processor-content v-if="isRefresh"-->
<!-- :jsr223-processor="environment.config.preProcessor"-->
<!-- :is-pre-processor="true"-->
<!-- :is-read-only="isReadOnly"/>-->
<!-- </el-tab-pane>-->
<el-tab-pane :label="$t('api_test.definition.request.all_pre_script')" name="prescript"> <el-tab-pane :label="$t('api_test.definition.request.all_pre_script')" name="prescript">
<environment-global-script v-if="isRefresh && environment.config.globalScriptConfig && environment.config.preProcessor && environment.config.preStepProcessor" <environment-global-script
:filter-request.sync="environment.config.globalScriptConfig.filterRequestPreScript" v-if="isRefresh && environment.config.globalScriptConfig && environment.config.preProcessor && environment.config.preStepProcessor"
:exec-after-private-script.sync="environment.config.globalScriptConfig.isPreScriptExecAfterPrivateScript" :filter-request.sync="environment.config.globalScriptConfig.filterRequestPreScript"
:conn-scenario.sync="environment.config.globalScriptConfig.connScenarioPreScript" :exec-after-private-script.sync="environment.config.globalScriptConfig.isPreScriptExecAfterPrivateScript"
:script-processor="environment.config.preProcessor" :conn-scenario.sync="environment.config.globalScriptConfig.connScenarioPreScript"
:scrpit-step-processor="environment.config.preStepProcessor" :script-processor="environment.config.preProcessor"
:is-pre-processor="true" :scrpit-step-processor="environment.config.preStepProcessor"
:is-read-only="isReadOnly" :is-pre-processor="true"
@updateGlobalScript="updateGlobalScript"/> :is-read-only="isReadOnly"
@updateGlobalScript="updateGlobalScript"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.all_post_script')" name="postscript"> <el-tab-pane :label="$t('api_test.definition.request.all_post_script')" name="postscript">
<environment-global-script v-if="isRefresh && environment.config.globalScriptConfig && environment.config.postProcessor && environment.config.postStepProcessor" <environment-global-script
:filter-request.sync="environment.config.globalScriptConfig.filterRequestPostScript" v-if="isRefresh && environment.config.globalScriptConfig && environment.config.postProcessor && environment.config.postStepProcessor"
:exec-after-private-script.sync="environment.config.globalScriptConfig.isPostScriptExecAfterPrivateScript" :filter-request.sync="environment.config.globalScriptConfig.filterRequestPostScript"
:conn-scenario.sync="environment.config.globalScriptConfig.connScenarioPostScript" :exec-after-private-script.sync="environment.config.globalScriptConfig.isPostScriptExecAfterPrivateScript"
:script-processor="environment.config.postProcessor" :conn-scenario.sync="environment.config.globalScriptConfig.connScenarioPostScript"
:scrpit-step-processor="environment.config.postStepProcessor" :script-processor="environment.config.postProcessor"
:is-pre-processor="false" :scrpit-step-processor="environment.config.postStepProcessor"
:is-read-only="isReadOnly" :is-pre-processor="false"
@updateGlobalScript="updateGlobalScript"/> :is-read-only="isReadOnly"
<!-- <el-switch v-model="environment.config.postProcessor.connScenario" active-text="关联场景结果"--> @updateGlobalScript="updateGlobalScript"/>
<!-- style="margin: 5px 5px 5px 5px"/>-->
<!-- <el-tooltip class="item" effect="dark" content="脚本步骤会统计到场景执行结果中,执行报错时会影响场景的最终执行结果" placement="right">-->
<!-- <i class="el-icon-info"/>-->
<!-- </el-tooltip>-->
<!-- <jsr233-processor-content v-if="isRefresh"-->
<!-- :jsr223-processor="environment.config.postProcessor"-->
<!-- :is-pre-processor="false"-->
<!-- :is-read-only="false"/>-->
</el-tab-pane> </el-tab-pane>
<!-- 认证配置 --> <!-- 认证配置 -->
<el-tab-pane :label="$t('api_test.definition.request.all_auth_config')" name="authConfig" v-if="isRefresh"> <el-tab-pane :label="$t('api_test.definition.request.all_auth_config')" name="authConfig" v-if="isRefresh">
<el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.definition.request.auth_config_info')" placement="top-start" slot="label"> <el-tooltip class="item-tabs" effect="dark" :content="$t('api_test.definition.request.auth_config_info')"
<span>{{$t('api_test.definition.request.all_auth_config')}}</span> placement="top-start" slot="label">
<span>{{ $t('api_test.definition.request.all_auth_config') }}</span>
</el-tooltip> </el-tooltip>
<ms-api-auth-config :is-read-only="isReadOnly" :request="environment.config.authManager"/> <ms-api-auth-config :is-read-only="isReadOnly" :request="environment.config.authManager"/>
</el-tab-pane> </el-tab-pane>
<!-- 全局断言-->
<el-tab-pane :label="$t('env_options.all_assertions')" name="assertions">
<el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item
:label="$t('error_report_library.use_error_report')"
prop="status">
<el-switch v-model="environment.config.useErrorCode" style="margin-right: 10px"/>
{{$t('error_report_library.use_desc')}}
</el-form-item>
</el-col>
</el-row>
<global-assertions
:assertions="environment.config.assertions"/>
</el-tab-pane>
</el-tabs> </el-tabs>
<div class="environment-footer"> <div class="environment-footer">
<ms-dialog-footer <ms-dialog-footer
@ -87,283 +88,302 @@
</template> </template>
<script> <script>
import MsApiScenarioVariables from "../ApiScenarioVariables"; import MsApiScenarioVariables from "../ApiScenarioVariables";
import MsApiKeyValue from "../ApiKeyValue"; import MsApiKeyValue from "../ApiKeyValue";
import MsDialogFooter from "../../../../common/components/MsDialogFooter"; import MsDialogFooter from "../../../../common/components/MsDialogFooter";
import {REQUEST_HEADERS} from "@/common/js/constants"; import {REQUEST_HEADERS} from "@/common/js/constants";
import {Environment} from "../../model/EnvironmentModel"; import {Environment} from "../../model/EnvironmentModel";
import MsApiHostTable from "../ApiHostTable"; import MsApiHostTable from "../ApiHostTable";
import MsDatabaseConfig from "../request/database/DatabaseConfig"; import MsDatabaseConfig from "../request/database/DatabaseConfig";
import MsEnvironmentHttpConfig from "./EnvironmentHttpConfig"; import MsEnvironmentHttpConfig from "./EnvironmentHttpConfig";
import MsEnvironmentCommonConfig from "./EnvironmentCommonConfig"; import MsEnvironmentCommonConfig from "./EnvironmentCommonConfig";
import MsEnvironmentSSLConfig from "./EnvironmentSSLConfig"; import MsEnvironmentSSLConfig from "./EnvironmentSSLConfig";
import MsApiAuthConfig from "@/business/components/api/definition/components/auth/ApiAuthConfig"; import MsApiAuthConfig from "@/business/components/api/definition/components/auth/ApiAuthConfig";
import MsTcpConfig from "@/business/components/api/test/components/request/tcp/TcpConfig"; import MsTcpConfig from "@/business/components/api/test/components/request/tcp/TcpConfig";
import {getUUID} from "@/common/js/utils"; import {getUUID} from "@/common/js/utils";
import Jsr233ProcessorContent from "@/business/components/api/automation/scenario/common/Jsr233ProcessorContent"; import Jsr233ProcessorContent from "@/business/components/api/automation/scenario/common/Jsr233ProcessorContent";
import {createComponent} from "@/business/components/api/definition/components/jmeter/components"; import {createComponent} from "@/business/components/api/definition/components/jmeter/components";
import EnvironmentGlobalScript from "@/business/components/api/test/components/environment/EnvironmentGlobalScript"; import EnvironmentGlobalScript from "@/business/components/api/test/components/environment/EnvironmentGlobalScript";
import GlobalAssertions from "@/business/components/api/definition/components/assertion/GlobalAssertions";
export default { export default {
name: "EnvironmentEdit", name: "EnvironmentEdit",
components: { components: {
MsTcpConfig, MsTcpConfig,
MsApiAuthConfig, GlobalAssertions,
Jsr233ProcessorContent, MsApiAuthConfig,
MsEnvironmentCommonConfig, Jsr233ProcessorContent,
MsEnvironmentHttpConfig, MsEnvironmentCommonConfig,
MsEnvironmentSSLConfig, MsEnvironmentHttpConfig,
EnvironmentGlobalScript, MsEnvironmentSSLConfig,
MsDatabaseConfig, MsApiHostTable, MsDialogFooter, MsApiKeyValue, MsApiScenarioVariables EnvironmentGlobalScript,
MsDatabaseConfig, MsApiHostTable, MsDialogFooter, MsApiKeyValue, MsApiScenarioVariables
},
props: {
environment: new Environment(),
projectId: String,
isReadOnly: {
type: Boolean,
default: false
}, },
props: { },
environment: new Environment(), data() {
projectId: String, return {
isReadOnly: { result: {},
type: Boolean, envEnable: false,
default: false isRefresh: true,
rules: {
name: [
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
{max: 64, message: this.$t('commons.input_limit', [1, 64]), trigger: 'blur'}
],
}, },
}, headerSuggestions: REQUEST_HEADERS,
data() { activeName: 'common'
return { }
result: {}, },
envEnable: false, created() {
isRefresh: true, if (!this.environment.config.preProcessor) {
rules: { this.environment.config.preProcessor = createComponent("JSR223PreProcessor");
name: [ }
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'}, if (!this.environment.config.postProcessor) {
{max: 64, message: this.$t('commons.input_limit', [1, 64]), trigger: 'blur'} this.environment.config.postProcessor = createComponent("JSR223PostProcessor");
], }
}, if (!this.environment.config.preStepProcessor) {
headerSuggestions: REQUEST_HEADERS, this.environment.config.preStepProcessor = createComponent("JSR223PreProcessor");
activeName: 'common' }
} if (!this.environment.config.postStepProcessor) {
}, this.environment.config.postStepProcessor = createComponent("JSR223PostProcessor");
created() { }
if(!this.environment.config.preProcessor){ if (!this.environment.config.globalScriptConfig) {
this.environment.config.globalScriptConfig = {
filterRequestPreScript: [],
filterRequestPostScript: [],
isPreScriptExecAfterPrivateScript: false,
isPostScriptExecAfterPrivateScript: false,
connScenarioPreScript: false,
connScenarioPostScript: false,
};
}
if (!this.environment.config.authManager) {
this.environment.config.authManager = {'hashTree': []};
}
if (!this.environment.config.authManager.hashTree) {
this.environment.config.authManager.hashTree = [];
}
if (!this.environment.config.assertions) {
this.environment.config.assertions = {
duration:{duration:0},
regex:[],
jsonPath:[],
xpath2:[],
jsr223:[],
document:{type:"json",data:{json:[],xml:[]}},
};
}
},
watch: {
environment: function (o) {
if (!this.environment.config.preProcessor) {
this.environment.config.preProcessor = createComponent("JSR223PreProcessor"); this.environment.config.preProcessor = createComponent("JSR223PreProcessor");
if (!this.environment.config.preProcessor.script) {
this.environment.config.preProcessor.script = "";
}
} }
if(!this.environment.config.postProcessor){ if (!this.environment.config.postProcessor) {
this.environment.config.postProcessor = createComponent("JSR223PostProcessor"); this.environment.config.postProcessor = createComponent("JSR223PostProcessor");
if (!this.environment.config.postProcessor.script) {
this.environment.config.postProcessor.script = "";
}
} }
if(!this.environment.config.preStepProcessor){ if (!this.environment.config.preStepProcessor) {
this.environment.config.preStepProcessor = createComponent("JSR223PreProcessor"); this.environment.config.preStepProcessor = createComponent("JSR223PreProcessor");
} }
if(!this.environment.config.postStepProcessor){ if (!this.environment.config.postStepProcessor) {
this.environment.config.postStepProcessor = createComponent("JSR223PostProcessor"); this.environment.config.postStepProcessor = createComponent("JSR223PostProcessor");
} }
if(!this.environment.config.globalScriptConfig){ if (!this.environment.config.globalScriptConfig) {
this.environment.config.globalScriptConfig = { this.environment.config.globalScriptConfig = {
filterRequestPreScript:[], filterRequestPreScript: [],
filterRequestPostScript:[], filterRequestPostScript: [],
isPreScriptExecAfterPrivateScript:false, isPreScriptExecAfterPrivateScript: false,
isPostScriptExecAfterPrivateScript:false, isPostScriptExecAfterPrivateScript: false,
connScenarioPreScript:false, connScenarioPreScript: false,
connScenarioPostScript:false, connScenarioPostScript: false,
}; };
} }
// if(!this.environment.config.postProcessor.connScenario){
// this.environment.config.postProcessor.connScenario = false; if (!this.environment.config.authManager) {
// } this.environment.config.authManager = {'hashTree': []};
if(!this.environment.config.authManager){
this.environment.config.authManager = {'hashTree':[]};
} }
if(!this.environment.config.authManager.hashTree){ if (!this.environment.config.authManager.hashTree) {
this.environment.config.authManager.hashTree = []; this.environment.config.authManager.hashTree = [];
} }
}, if (!this.environment.config.assertions) {
this.environment.config.assertions = {
duration:{duration:0},
regex:[],
jsonPath:[],
xpath2:[],
jsr223:[],
document:{type:"json",data:{json:[],xml:[]}},
};
}
watch: { this.isRefresh = false;
environment: function (o) { this.$nextTick(() => {
if(!this.environment.config.preProcessor){ this.isRefresh = true;
this.environment.config.preProcessor = createComponent("JSR223PreProcessor"); });
if(!this.environment.config.preProcessor.script){ this.envEnable = o.enable;
this.environment.config.preProcessor.script = ""; }
} },
methods: {
updateGlobalScript(isPreScript, filedName, value) {
if (isPreScript) {
if (filedName === "connScenario") {
this.environment.config.globalScriptConfig.connScenarioPreScript = value;
} else if (filedName === "execAfterPrivateScript") {
this.environment.config.globalScriptConfig.isPreScriptExecAfterPrivateScript = value;
} else if (filedName === "filterRequest") {
this.environment.config.globalScriptConfig.filterRequestPreScript = value;
} }
if(!this.environment.config.postProcessor){ } else {
this.environment.config.postProcessor = createComponent("JSR223PostProcessor"); if (filedName === "connScenario") {
if(!this.environment.config.postProcessor.script){ this.environment.config.globalScriptConfig.connScenarioPostScript = value;
this.environment.config.postProcessor.script = ""; } else if (filedName === "execAfterPrivateScript") {
} this.environment.config.globalScriptConfig.isPostScriptExecAfterPrivateScript = value;
} else if (filedName === "filterRequest") {
this.environment.config.globalScriptConfig.filterRequestPostScript = value;
} }
if(!this.environment.config.preStepProcessor){
this.environment.config.preStepProcessor = createComponent("JSR223PreProcessor");
}
if(!this.environment.config.postStepProcessor){
this.environment.config.postStepProcessor = createComponent("JSR223PostProcessor");
}
if(!this.environment.config.globalScriptConfig){
this.environment.config.globalScriptConfig = {
filterRequestPreScript:[],
filterRequestPostScript:[],
isPreScriptExecAfterPrivateScript:false,
isPostScriptExecAfterPrivateScript:false,
connScenarioPreScript:false,
connScenarioPostScript:false,
};
}
if(!this.environment.config.authManager){
this.environment.config.authManager = {'hashTree':[]};
}
if(!this.environment.config.authManager.hashTree){
this.environment.config.authManager.hashTree = [];
}
this.isRefresh = false;
this.$nextTick(() => {
this.isRefresh = true;
});
this.envEnable = o.enable;
} }
}, },
methods: { save() {
updateGlobalScript(isPreScript,filedName,value){ this.$refs['environment'].validate((valid) => {
if(isPreScript){ if (valid && this.$refs.commonConfig.validate() && this.$refs.httpConfig.validate()) {
if(filedName === "connScenario"){ this._save(this.environment);
this.environment.config.globalScriptConfig.connScenarioPreScript = value;
}else if(filedName === "execAfterPrivateScript"){
this.environment.config.globalScriptConfig.isPreScriptExecAfterPrivateScript = value;
}else if(filedName === "filterRequest"){
this.environment.config.globalScriptConfig.filterRequestPreScript = value;
}
}else {
if(filedName === "connScenario"){
this.environment.config.globalScriptConfig.connScenarioPostScript = value;
}else if(filedName === "execAfterPrivateScript"){
this.environment.config.globalScriptConfig.isPostScriptExecAfterPrivateScript = value;
}else if(filedName === "filterRequest"){
this.environment.config.globalScriptConfig.filterRequestPostScript = value;
}
} }
}, });
save() { },
this.$refs['environment'].validate((valid) => { validate() {
if (valid && this.$refs.commonConfig.validate() && this.$refs.httpConfig.validate()) { let isValidate = false;
this._save(this.environment); this.$refs['environment'].validate((valid) => {
} if (valid && this.$refs.commonConfig.validate() && this.$refs.httpConfig.validate()) {
}); isValidate = true;
}, } else {
validate() { isValidate = false;
let isValidate = false;
this.$refs['environment'].validate((valid) => {
if (valid && this.$refs.commonConfig.validate() && this.$refs.httpConfig.validate()) {
isValidate = true;
} else {
isValidate = false;
}
});
return isValidate;
},
geFiles(obj) {
let uploadFiles = [];
obj.uploadIds = [];
if (obj.config && obj.config.sslConfig && obj.config.sslConfig.files) {
obj.config.sslConfig.files.forEach(item => {
if (item.file && item.file.size > 0) {
if (!item.id) {
item.name = item.file.name;
item.id = getUUID();
}
obj.uploadIds.push(item.id);
uploadFiles.push(item.file);
}
})
} }
return uploadFiles; });
}, return isValidate;
check (items) { },
let repeatKey = ""; geFiles(obj) {
items.forEach((item, index) => { let uploadFiles = [];
items.forEach((row, rowIndex) => { obj.uploadIds = [];
if (item.name === row.name && index !== rowIndex) { if (obj.config && obj.config.sslConfig && obj.config.sslConfig.files) {
repeatKey = item.name; obj.config.sslConfig.files.forEach(item => {
if (item.file && item.file.size > 0) {
if (!item.id) {
item.name = item.file.name;
item.id = getUUID();
} }
}); obj.uploadIds.push(item.id);
uploadFiles.push(item.file);
}
})
}
return uploadFiles;
},
check(items) {
let repeatKey = "";
items.forEach((item, index) => {
items.forEach((row, rowIndex) => {
if (item.name === row.name && index !== rowIndex) {
repeatKey = item.name;
}
}); });
return repeatKey; });
}, return repeatKey;
_save(environment) { },
if(!this.projectId){ _save(environment) {
this.$warning(this.$t('api_test.select_project')); if (!this.projectId) {
this.$warning(this.$t('api_test.select_project'));
return;
}
if (environment && environment.config && environment.config.commonConfig && environment.config.commonConfig.variables) {
let repeatKey = this.check(environment.config.commonConfig && environment.config.commonConfig.variables);
if (repeatKey !== "") {
this.$warning(this.$t('api_test.environment.common_config') + "【" + repeatKey + "】" + this.$t('load_test.param_is_duplicate'));
return; return;
} }
if(environment && environment.config && environment.config.commonConfig &&environment.config.commonConfig.variables){ }
let repeatKey = this.check(environment.config.commonConfig &&environment.config.commonConfig.variables); let bodyFiles = this.geFiles(environment);
if (repeatKey !== "") { let param = this.buildParam(environment);
this.$warning(this.$t('api_test.environment.common_config') + "【" + repeatKey + "】" + this.$t('load_test.param_is_duplicate')); let url = '/api/environment/add';
return ; if (param.id) {
} url = '/api/environment/update';
}
this.$fileUpload(url, null, bodyFiles, param, response => {
//this.result = this.$post(url, param, response => {
if (!param.id) {
environment.id = response.data;
} }
let bodyFiles = this.geFiles(environment); this.$success(this.$t('commons.save_success'));
let param = this.buildParam(environment); this.$emit('refreshAfterSave'); //EnvironmentList.vue使
let url = '/api/environment/add'; this.cancel();
if (param.id) { });
url = '/api/environment/update';
}
this.$fileUpload(url, null, bodyFiles, param, response => {
//this.result = this.$post(url, param, response => {
if (!param.id) {
environment.id = response.data;
}
this.$success(this.$t('commons.save_success'));
this.$emit('refreshAfterSave'); //EnvironmentList.vue使
this.cancel();
});
},
buildParam: function (environment) {
let param = {};
Object.assign(param, environment);
let hosts = param.config.commonConfig.hosts;
if (hosts != undefined) {
let validHosts = [];
// host
hosts.forEach(host => {
if (host.status === '') {
validHosts.push(host);
}
});
param.config.commonConfig.hosts = validHosts;
}
param.config = JSON.stringify(param.config);
return param;
},
cancel() {
this.$emit('close');
},
clearValidate() {
this.$refs["environment"].clearValidate();
},
}, },
} buildParam: function (environment) {
let param = {};
Object.assign(param, environment);
let hosts = param.config.commonConfig.hosts;
if (hosts != undefined) {
let validHosts = [];
// host
hosts.forEach(host => {
if (host.status === '') {
validHosts.push(host);
}
});
param.config.commonConfig.hosts = validHosts;
}
param.config = JSON.stringify(param.config);
return param;
},
cancel() {
this.$emit('close');
},
clearValidate() {
this.$refs["environment"].clearValidate();
},
},
}
</script> </script>
<style scoped> <style scoped>
.el-main { .el-main {
border: solid 1px #EBEEF5; border: solid 1px #EBEEF5;
margin-left: 200px; margin-left: 200px;
min-height: 400px; min-height: 400px;
max-height: 550px; max-height: 550px;
} }
.el-row { .el-row {
margin-bottom: 15px; margin-bottom: 15px;
} }
.environment-footer { .environment-footer {
margin-top: 15px; margin-top: 15px;
float: right; float: right;
} }
span { span {
display: block; display: block;
margin-bottom: 15px; margin-bottom: 15px;
} }
span:not(:first-child) { span:not(:first-child) {
margin-top: 15px; margin-top: 15px;
} }
</style> </style>

View File

@ -30,7 +30,7 @@
</el-menu-item> </el-menu-item>
<el-menu-item index="/project" onselectstart="return false" <el-menu-item index="/project" onselectstart="return false"
v-permission="['PROJECT_USER:READ', 'PROJECT_ENVIRONMENT:READ', 'PROJECT_OPERATING_LOG:READ', 'PROJECT_FILE:READ+JAR', 'PROJECT_FILE:READ+FILE', 'PROJECT_CUSTOM_CODE:READ']"> v-permission="['PROJECT_USER:READ', 'PROJECT_ENVIRONMENT:READ', 'PROJECT_OPERATING_LOG:READ', 'PROJECT_FILE:READ+JAR', 'PROJECT_FILE:READ+FILE', 'PROJECT_CUSTOM_CODE:READ','PROJECT_ERROR_REPORT_LIBRARY:READ']">
{{ $t('commons.project_setting') }} {{ $t('commons.project_setting') }}
</el-menu-item> </el-menu-item>

View File

@ -27,6 +27,9 @@
v-permission="['PROJECT_CUSTOM_CODE:READ']"> v-permission="['PROJECT_CUSTOM_CODE:READ']">
{{ $t('project.code_segment.code_segment') }} {{ $t('project.code_segment.code_segment') }}
</el-menu-item> </el-menu-item>
<el-menu-item :index="'/project/errorreportlibrary'" v-xpack >
{{ $t("error_report_library.name") }}
</el-menu-item>
<el-menu-item :index="'/project/log'" popper-class="submenu" v-permission="['PROJECT_OPERATING_LOG:READ']"> <el-menu-item :index="'/project/log'" popper-class="submenu" v-permission="['PROJECT_OPERATING_LOG:READ']">
{{ $t('project.log') }} {{ $t('project.log') }}
</el-menu-item> </el-menu-item>

View File

@ -1,3 +1,5 @@
import {errorReportLibrary} from "@/business/components/xpack/router";
const ProjectSetting = () => import('@/business/components/project/ProjectSetting') const ProjectSetting = () => import('@/business/components/project/ProjectSetting')
const ProjectHome = () => import('@/business/components/project/home/ProjectHome') const ProjectHome = () => import('@/business/components/project/home/ProjectHome')
const ProjectMember = () => import('@/business/components/project/menu/Member') const ProjectMember = () => import('@/business/components/project/menu/Member')
@ -57,5 +59,6 @@ export default {
component: ProjectAppManage component: ProjectAppManage
}, },
...ProjectVersion, ...ProjectVersion,
...requireContext.keys().map(key => requireContext(key).errorReportLibrary),
] ]
}; };

View File

@ -94,7 +94,6 @@ export default {
let data = response.data.barChartDTO; let data = response.data.barChartDTO;
let pieData = response.data.pieChartDTO; let pieData = response.data.pieChartDTO;
let selectTableData = response.data.tableDTOs; let selectTableData = response.data.tableDTOs;
console.info(response.data);
this.initPic(data, pieData, selectTableData); this.initPic(data, pieData, selectTableData);
}, error => { }, error => {
this.loading = false; this.loading = false;

@ -1 +1 @@
Subproject commit 634572fa145f83ea9d4e90cc0f610ee9a54fd668 Subproject commit fa028c4791370e1ea66eaa60dfa22eb0b0d70ea3

View File

@ -2609,6 +2609,13 @@ export default {
api_case: 'API Case', api_case: 'API Case',
}, },
permission: { permission: {
project_error_report_library: {
name: "Error report library",
read: "READ",
create: "CREATE",
edit: "EDIT",
delete: "DELETE",
},
system_user: { system_user: {
name: "User", name: "User",
read: "READ", read: "READ",
@ -2901,6 +2908,24 @@ export default {
project: "Project", project: "Project",
report: "Report Statistics" report: "Report Statistics"
} }
},
env_options: {
all_assertions: "Assertions"
},
error_report_library: {
name: "Error report",
assertion: "Error code assertion",
use_error_report: "Use error code",
use_desc: "In case of conflict between error code and error assertions, it is treated as error code",
option: {
name: "Err code",
error_code: "Err code",
match_type: "Match",
status: "Status",
is_open: "Is open",
},
match_type: {
text: "TXT"
}
} }
}; };

View File

@ -2612,6 +2612,13 @@ export default {
api_case: '接口用例' api_case: '接口用例'
}, },
permission: { permission: {
project_error_report_library: {
name: "误报库",
read: "查看误报",
create: "创建误报",
edit: "修改误报",
delete: "刪除误报",
},
system_user: { system_user: {
name: "用户", name: "用户",
read: "查询用户", read: "查询用户",
@ -2905,5 +2912,24 @@ export default {
project: "项目设置", project: "项目设置",
report: "报表统计" report: "报表统计"
} }
},
env_options: {
all_assertions: "全局断言"
},
error_report_library: {
name: "误报库",
assertion: "误报断言",
use_error_report: "启用误报",
use_desc: "失败断言与误报规则冲突时统一处理为误报",
option: {
name: "误报",
error_code: "错误码",
match_type: "匹配类型",
status: "状态",
is_open: "启用状态",
},
match_type: {
text: "文本"
}
} }
}; };

View File

@ -2612,6 +2612,13 @@ export default {
api_case: '接口用例' api_case: '接口用例'
}, },
permission: { permission: {
project_error_report_library: {
name: "誤報庫",
read: "查看誤報",
create: "創建誤報",
edit: "修改誤報",
delete: "刪除誤報",
},
system_user: { system_user: {
name: "用戶", name: "用戶",
read: "查詢用戶", read: "查詢用戶",
@ -2905,5 +2912,24 @@ export default {
project: "項目設置", project: "項目設置",
report: "報表統計" report: "報表統計"
} }
},
env_options: {
all_assertions: "全局斷言"
},
error_report_library: {
name: "誤報庫",
assertion: "誤報斷言",
use_error_report: "啟用誤報",
use_desc: "失敗斷言與誤報規則衝突時統一處理為誤報",
option: {
name: "誤報",
error_code: "錯誤碼",
match_type: "匹配類型",
status: "狀態",
is_open: "啟用狀態",
},
match_type: {
text: "文本"
}
} }
}; };

View File

@ -51,7 +51,6 @@ export default {
let data = JSON.parse(reportData.dataOption); let data = JSON.parse(reportData.dataOption);
data.selectOption = selectOption; data.selectOption = selectOption;
this.dataOption = data; this.dataOption = data;
console.info(this.dataOption);
this.reloadChart(); this.reloadChart();
} }
}, (error) => { }, (error) => {