Conflicts:
	backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java
This commit is contained in:
wenyann 2021-01-18 18:07:57 +08:00
commit 3c36edbb96
144 changed files with 5146 additions and 1077 deletions

View File

@ -114,6 +114,7 @@ public class ApiDefinitionController {
@PostMapping(value = "/run", consumes = {"multipart/form-data"})
public String run(@RequestPart("request") RunDefinitionRequest request, @RequestPart(value = "files") List<MultipartFile> bodyFiles) {
request.setReportId(null);
return apiDefinitionService.run(request, bodyFiles);
}

View File

@ -23,6 +23,9 @@ public class RunScenarioRequest {
private String runMode;
//测试情景和测试计划的关联ID
private String planScenarioId;
private List<String> planCaseIds;
private String reportUserID;

View File

@ -0,0 +1,38 @@
package io.metersphere.api.dto.automation;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Map;
@Setter
@Getter
public class SchedulePlanScenarioExecuteRequest {
private String id;
private String reportId;
private String projectId;
private String environmentId;
private String triggerMode;
private String executeType;
private String runMode;
//测试情景和测试计划的关联ID
private String testPlanID;
private List<String> planCaseIds;
private String reportUserID;
//key: test_plan.id, value: test_plan_api_scenario <->scenarioValue
private Map<String,Map<String,String>> testPlanScenarioIDMap;
private String testPlanReportId;
}

View File

@ -54,6 +54,7 @@ public class MsScenario extends MsTestElement {
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -18,6 +18,7 @@ import java.util.List;
public class MsTestPlan extends MsTestElement {
private String type = "TestPlan";
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
final HashTree testPlanTree = tree.add(getPlan());
if (CollectionUtils.isNotEmpty(hashTree)) {

View File

@ -20,6 +20,7 @@ public class MsThreadGroup extends MsTestElement {
private String type = "ThreadGroup";
private boolean enableCookieShare;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
final HashTree groupTree = tree.add(getThreadGroup());
if ((config != null && config.isEnableCookieShare()) || enableCookieShare) {

View File

@ -24,6 +24,7 @@ public class MsAssertions extends MsTestElement {
private MsAssertionDuration duration;
private String type = "Assertions";
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (this.isEnable()) {
addAssertions(tree);
@ -79,6 +80,8 @@ public class MsAssertions extends MsTestElement {
case "Response Data":
assertion.setTestFieldResponseData();
break;
default:
break;
}
return assertion;
}

View File

@ -51,6 +51,7 @@ public class MsAuthManager extends MsTestElement {
@JSONField(ordinal = 28)
private String environment;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -25,6 +25,7 @@ public class MsHeaderManager extends MsTestElement {
@JSONField(ordinal = 20)
private List<KeyValue> headers;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -24,6 +24,7 @@ public class MsIfController extends MsTestElement {
private String operator;
private String value;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
@ -39,7 +40,7 @@ public class MsIfController extends MsTestElement {
private IfController ifController() {
IfController ifController = new IfController();
ifController.setEnabled(true);
ifController.setName(this.getLabel());
ifController.setName(this.getLabelName());
ifController.setCondition(this.getCondition());
ifController.setProperty(TestElement.TEST_CLASS, IfController.class.getName());
ifController.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("IfControllerPanel"));
@ -55,7 +56,7 @@ public class MsIfController extends MsTestElement {
return StringUtils.isNotBlank(variable) && StringUtils.isNotBlank(operator) && StringUtils.isNotBlank(value);
}
public String getLabel() {
public String getLabelName() {
if (isValid()) {
String label = variable + " " + operator;
if (StringUtils.isNotBlank(value)) {

View File

@ -38,14 +38,15 @@ public class MsLoopController extends MsTestElement {
@JSONField(ordinal = 23)
private MsWhileController whileController;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
GenericController controller = controller();
if (controller == null)
if (controller == null) {
return;
}
final HashTree groupTree = tree.add(controller);
if (CollectionUtils.isNotEmpty(hashTree)) {
hashTree.forEach(el -> {

View File

@ -24,6 +24,7 @@ import java.util.List;
@JSONType(typeName = "DNSCacheManager")
public class MsDNSCacheManager extends MsTestElement {
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -27,6 +27,7 @@ public class MsExtract extends MsTestElement {
private List<MsExtractXPath> xpath;
private String type = "Extract";
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -27,6 +27,7 @@ public class MsJSR223Processor extends MsTestElement {
@JSONField(ordinal = 21)
private String scriptLanguage;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -27,7 +27,7 @@ public class MsJSR223PostProcessor extends MsTestElement {
@JSONField(ordinal = 21)
private String scriptLanguage;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -27,6 +27,7 @@ public class MsJSR223PreProcessor extends MsTestElement {
@JSONField(ordinal = 21)
private String scriptLanguage;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -54,14 +54,15 @@ public class MsDubboSampler extends MsTestElement {
@JSONField(ordinal = 60)
private Object requestResult;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) {
if (this.getReferenced() != null && "Deleted".equals(this.getReferenced())) {
return;
}
if (this.getReferenced() != null && this.getReferenced().equals("REF")) {
if (this.getReferenced() != null && "REF".equals(this.getReferenced())) {
this.getRefElement(this);
}

View File

@ -31,7 +31,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Data
@EqualsAndHashCode(callSuper = true)
@JSONType(typeName = "HTTPSamplerProxy")
@ -86,11 +85,12 @@ public class MsHTTPSamplerProxy extends MsTestElement {
@JSONField(ordinal = 35)
private Object requestResult;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && this.getReferenced().equals("REF")) {
if (this.getReferenced() != null && "REF".equals(this.getReferenced())) {
this.getRefElement(this);
}
HTTPSamplerProxy sampler = new HTTPSamplerProxy();
@ -109,9 +109,9 @@ public class MsHTTPSamplerProxy extends MsTestElement {
sampler.setFollowRedirects(this.isFollowRedirects());
sampler.setUseKeepAlive(true);
sampler.setDoMultipart(this.isDoMultipartPost());
if(config != null && config.getConfig() != null){
if (config != null && config.getConfig() != null) {
config.setConfig(config.getConfig());
}else{
} else {
config.setConfig(getEnvironmentConfig(useEnvironment));
}
@ -183,7 +183,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
if (!StringUtils.equals(this.getMethod(), "GET")) {
if (this.body != null) {
List<KeyValue> bodyParams = this.body.getBodyParams(sampler, this.getId());
if (StringUtils.isNotEmpty(this.body.getType()) && this.body.getType().equals("Form Data")) {
if (StringUtils.isNotEmpty(this.body.getType()) && "Form Data".equals(this.body.getType())) {
sampler.setDoMultipart(true);
}
if (CollectionUtils.isNotEmpty(bodyParams)) {

View File

@ -51,11 +51,12 @@ public class MsJDBCSampler extends MsTestElement {
@JSONField(ordinal = 28)
private String dataSourceId;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && this.getReferenced().equals("REF")) {
if (this.getReferenced() != null && "REF".equals(this.getReferenced())) {
this.getRefElement(this);
}
if (StringUtils.isNotEmpty(dataSourceId)) {

View File

@ -59,6 +59,7 @@ public class MsTCPSampler extends MsTestElement {
@JSONField(ordinal = 36)
private String useEnvironment;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -24,6 +24,7 @@ public class MsConstantTimer extends MsTestElement {
@JSONField(ordinal = 21)
private String delay;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
if (!this.isEnable()) {
return;

View File

@ -40,13 +40,17 @@ public class Body {
if (StringUtils.equals(type, FORM_DATA) || StringUtils.equals(type, WWW_FROM)
|| StringUtils.equals(type, BINARY)) {
return true;
} else return false;
} else {
return false;
}
}
public boolean isOldKV() {
if (StringUtils.equals(type, KV)) {
return true;
} else return false;
} else {
return false;
}
}
public List<KeyValue> getBodyParams(HTTPSamplerProxy sampler, String requestId) {
@ -63,7 +67,7 @@ public class Body {
if (!this.isJson()) {
sampler.setPostBodyRaw(true);
} else {
if (StringUtils.isNotEmpty(this.format) && this.format.equals("JSON-SCHEMA") && this.getJsonSchema() != null) {
if (StringUtils.isNotEmpty(this.format) && "JSON-SCHEMA".equals(this.format) && this.getJsonSchema() != null) {
this.raw = JSONSchemaGenerator.getJson(com.alibaba.fastjson.JSON.toJSONString(this.getJsonSchema()));
}
}

View File

@ -12,6 +12,7 @@ import io.metersphere.i18n.Translator;
import io.metersphere.notice.sender.NoticeModel;
import io.metersphere.notice.service.NoticeSendService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.track.service.TestPlanReportService;
import io.metersphere.track.service.TestPlanTestCaseService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -48,6 +49,8 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
private ApiDefinitionExecResultService apiDefinitionExecResultService;
private TestPlanReportService testPlanReportService;
private ApiScenarioReportService apiScenarioReportService;
@ -92,6 +95,10 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
if (apiDefinitionExecResultService == null) {
LogUtil.error("apiDefinitionExecResultService is required");
}
testPlanReportService = CommonBeanFactory.getBean(TestPlanReportService.class);
if (testPlanReportService == null) {
LogUtil.error("testPlanReportService is required");
}
apiScenarioReportService = CommonBeanFactory.getBean(ApiScenarioReportService.class);
if (apiScenarioReportService == null) {
@ -163,16 +170,27 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl
apiReportService.complete(testResult, report);
} else if (StringUtils.equals(this.runMode, ApiRunMode.DELIMIT.name())) {
// 调试操作不需要存储结果
apiDefinitionService.addResult(testResult);
if (StringUtils.isBlank(debugReportId)) {
if (StringUtils.isBlank(debugReportId)) {
apiDefinitionService.addResult(testResult);
} else {
apiDefinitionService.addResult(testResult);
apiDefinitionExecResultService.saveApiResult(testResult, ApiRunMode.DELIMIT.name());
}
} else if (StringUtils.equals(this.runMode, ApiRunMode.API_PLAN.name())) {
} else if (StringUtils.equalsAny(this.runMode, ApiRunMode.API_PLAN.name(), ApiRunMode.SCHEDULE_API_PLAN.name())) {
apiDefinitionService.addResult(testResult);
apiDefinitionExecResultService.saveApiResult(testResult, ApiRunMode.API_PLAN.name());
} else if (StringUtils.equalsAny(this.runMode, ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name())) {
//测试计划定时任务-接口执行逻辑的话需要同步测试计划的报告数据
if (StringUtils.equals(this.runMode, ApiRunMode.SCHEDULE_API_PLAN.name())) {
apiDefinitionExecResultService.saveApiResultByScheduleTask(testResult, ApiRunMode.SCHEDULE_API_PLAN.name());
List<String> testPlanReportIdList = new ArrayList<>();
testPlanReportIdList.add(debugReportId);
testPlanReportService.updateReport(testPlanReportIdList,ApiRunMode.SCHEDULE_API_PLAN.name(),ReportTriggerMode.SCHEDULE.name());
}else {
apiDefinitionExecResultService.saveApiResult(testResult, ApiRunMode.API_PLAN.name());
}
} else if (StringUtils.equalsAny(this.runMode, ApiRunMode.SCENARIO.name(), ApiRunMode.SCENARIO_PLAN.name(), ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) {
// 执行报告不需要存储由用户确认后在存储
testResult.setTestId(testId);
ApiScenarioReport scenarioReport = apiScenarioReportService.complete(testResult, this.runMode);

View File

@ -40,16 +40,16 @@ public class TestResult {
this.passAssertions += count;
}
private static final String separator = "<->";
private static final String SEPARATOR = "<->";
public void addScenario(ScenarioResult result) {
Map<String, List<RequestResult>> requestResultMap = new LinkedHashMap<>();
if (result != null && CollectionUtils.isNotEmpty(result.getRequestResults())) {
result.getRequestResults().forEach(item -> {
if (StringUtils.isNotEmpty(item.getName()) && item.getName().indexOf(separator) != -1) {
String array[] = item.getName().split(separator);
if (StringUtils.isNotEmpty(item.getName()) && item.getName().indexOf(SEPARATOR) != -1) {
String array[] = item.getName().split(SEPARATOR);
String scenarioName = array[array.length - 1];
item.setName(item.getName().replace(separator + scenarioName, ""));
item.setName(item.getName().replace(SEPARATOR + scenarioName, ""));
if (requestResultMap.containsKey(scenarioName)) {
requestResultMap.get(scenarioName).add(item);
} else {

View File

@ -157,7 +157,7 @@ public class JmeterDocumentParser {
u += k + "=" + ScriptEngineUtils.calculate(v);
return u;
});
ele.setTextContent(url + ((params != null && !params.equals("?")) ? params : ""));
ele.setTextContent(url + ((params != null && !"?".equals(params)) ? params : ""));
break;
case "Argument.value":
String textContent = ele.getTextContent();

View File

@ -416,6 +416,112 @@ public class ApiAutomationService {
jMeterService.runDefinition(request.getId(), generateHashTree(apiScenarios, request, true), request.getReportId(), runMode);
return request.getId();
}
/**
* 测试计划的定时任务--执行场景案例
*
* @param request
* @return
*/
public String run(SchedulePlanScenarioExecuteRequest request) {
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = new ListedHashTree();
Map<String, Map<String,String>> testPlanScenarioIdMap = request.getTestPlanScenarioIDMap();
for (Map.Entry<String, Map<String,String>> entry : testPlanScenarioIdMap.entrySet()) {
String testPlanID = entry.getKey();
Map<String,String> planScenarioIdMap = entry.getValue();
List<ApiScenarioWithBLOBs> apiScenarios = extApiScenarioMapper.selectIds(new ArrayList<>(planScenarioIdMap.keySet()));
try {
boolean isFirst = true;
for (ApiScenarioWithBLOBs item : apiScenarios) {
String apiScenarioID = item.getId();
String planScenarioID = planScenarioIdMap.get(apiScenarioID);
if(StringUtils.isEmpty(planScenarioID)){
continue;
}
if (item.getStepTotal() == 0) {
// 只有一个场景且没有测试步骤则提示
if (apiScenarios.size() == 1) {
MSException.throwException((item.getName() + "" + Translator.get("automation_exec_info")));
}
LogUtil.warn(item.getName() + "" + Translator.get("automation_exec_info"));
continue;
}
MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName());
group.setName(UUID.randomUUID().toString());
// 批量执行的结果直接存储为报告
if (isFirst) {
group.setName(request.getId());
isFirst = false;
}
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JSONObject element = JSON.parseObject(item.getScenarioDefinition());
MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
new TypeReference<LinkedList<MsTestElement>>() {
});
scenario.setHashTree(elements);
}
if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
scenario.setVariables(variables);
}
group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>();
scenarios.add(scenario);
// 创建场景报告
//不同的运行模式第二个参数入参不同
createScenarioReport(group.getName(),
planScenarioID+":"+request.getTestPlanReportId() ,
item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
group.setHashTree(scenarios);
testPlan.getHashTree().add(group);
}
} catch (Exception ex) {
MSException.throwException(ex.getMessage());
}
}
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
String runMode = ApiRunMode.SCHEDULE_SCENARIO_PLAN.name();
// 调用执行方法
jMeterService.runDefinition(request.getId(), jmeterHashTree, request.getReportId(), runMode);
return request.getId();
}
/**
* 获取前台查询条件查询的所有(未经分页筛选)数据ID
*
* @param moduleIds 模块ID_前台查询时所选择的
* @param name 搜索条件_名称_前台查询时所输入的
* @param projectId 所属项目_前台查询时所在项目
* @param filters 过滤集合__前台查询时的过滤条件
* @param unSelectIds 未勾选ID_前台没有勾选的ID
* @return
*/
private List<String> getAllScenarioIdsByFontedSelect(List<String> moduleIds, String name, String projectId, List<String> filters, List<String> unSelectIds) {
ApiScenarioRequest selectRequest = new ApiScenarioRequest();
selectRequest.setModuleIds(moduleIds);
selectRequest.setName(name);
selectRequest.setProjectId(projectId);
selectRequest.setFilters(filters);
selectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
List<ApiScenarioDTO> list = extApiScenarioMapper.list(selectRequest);
List<String> allIds = list.stream().map(ApiScenarioDTO::getId).collect(Collectors.toList());
List<String> ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList());
return ids;
}
/**
* 场景测试执行
*
@ -453,28 +559,6 @@ public class ApiAutomationService {
return dto;
}
/**
* 获取前台查询条件查询的所有(未经分页筛选)数据ID
*
* @param moduleIds 模块ID_前台查询时所选择的
* @param name 搜索条件_名称_前台查询时所输入的
* @param projectId 所属项目_前台查询时所在项目
* @param filters 过滤集合__前台查询时的过滤条件
* @param unSelectIds 未勾选ID_前台没有勾选的ID
* @return
*/
private List<String> getAllScenarioIdsByFontedSelect(List<String> moduleIds, String name, String projectId, List<String> filters, List<String> unSelectIds) {
ApiScenarioRequest selectRequest = new ApiScenarioRequest();
selectRequest.setModuleIds(moduleIds);
selectRequest.setName(name);
selectRequest.setProjectId(projectId);
selectRequest.setFilters(filters);
selectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
List<ApiScenarioDTO> list = extApiScenarioMapper.list(selectRequest);
List<String> allIds = list.stream().map(ApiScenarioDTO::getId).collect(Collectors.toList());
List<String> ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList());
return ids;
}
public String addScenarioToPlan(SaveApiPlanRequest request) {
if (CollectionUtils.isEmpty(request.getPlanIds())) {

View File

@ -5,6 +5,7 @@ import io.metersphere.api.dto.datacount.ExecutedCaseInfoResult;
import io.metersphere.api.jmeter.TestResult;
import io.metersphere.base.domain.ApiDefinitionExecResult;
import io.metersphere.base.domain.ApiDefinitionExecResultExample;
import io.metersphere.base.domain.TestPlanApiCase;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ext.ExtApiDefinitionExecResultMapper;
import io.metersphere.commons.constants.ApiRunMode;
@ -59,6 +60,43 @@ public class ApiDefinitionExecResultService {
});
}
/**
* 定时任务触发的保存逻辑
* 定时任务时userID要改为定时任务中的用户
* @param result
* @param type
*/
public void saveApiResultByScheduleTask(TestResult result, String type) {
result.getScenarios().get(0).getRequestResults().forEach(item -> {
ApiDefinitionExecResult saveResult = new ApiDefinitionExecResult();
saveResult.setId(UUID.randomUUID().toString());
saveResult.setCreateTime(System.currentTimeMillis());
saveResult.setName(item.getName());
saveResult.setResourceId(item.getName());
saveResult.setContent(JSON.toJSONString(item));
saveResult.setStartTime(item.getStartTime());
String status = item.isSuccess() ? "success" : "error";
saveResult.setEndTime(item.getResponseResult().getResponseTime());
saveResult.setType(type);
saveResult.setStatus(status);
String userID = null;
if (StringUtils.equals(type, ApiRunMode.SCHEDULE_API_PLAN.name())) {
TestPlanApiCase apiCase = testPlanApiCaseService.getById(item.getName());
String scheduleCreateUser = testPlanService.findScheduleCreateUserById(apiCase.getTestPlanId());
userID = scheduleCreateUser;
apiCase.setStatus(status);
testPlanApiCaseService.updateByPrimaryKeySelective(apiCase);
}else {
userID = Objects.requireNonNull(SessionUtils.getUser()).getId();
testPlanApiCaseService.setExecResult(item.getName(), status);
}
saveResult.setUserId(userID);
apiDefinitionExecResultMapper.insert(saveResult);
});
}
public void deleteByResourceId(String resourceId) {
ApiDefinitionExecResultExample example = new ApiDefinitionExecResultExample();
example.createCriteria().andResourceIdEqualTo(resourceId);

View File

@ -9,6 +9,7 @@ import io.metersphere.api.dto.APIReportResult;
import io.metersphere.api.dto.ApiTestImportRequest;
import io.metersphere.api.dto.automation.ApiScenarioRequest;
import io.metersphere.api.dto.automation.ReferenceDTO;
import io.metersphere.api.dto.automation.RunScenarioRequest;
import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
@ -29,6 +30,7 @@ import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*;
import io.metersphere.i18n.Translator;
@ -43,6 +45,7 @@ import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree;
import org.aspectj.util.FileUtil;
import org.aspectj.weaver.ast.Test;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
@ -187,7 +190,7 @@ public class ApiDefinitionService {
.andProtocolEqualTo(request.getProtocol()).andPathEqualTo(request.getPath())
.andProjectIdEqualTo(request.getProjectId()).andIdNotEqualTo(request.getId());
Project project = projectMapper.selectByPrimaryKey(request.getProjectId());
if (apiDefinitionMapper.countByExample(example) > 0 && !project.getRepeatable()) {
if (apiDefinitionMapper.countByExample(example) > 0 && (project.getRepeatable() == null || !project.getRepeatable())) {
MSException.throwException(Translator.get("api_definition_url_not_repeating"));
}
} else {
@ -339,58 +342,6 @@ public class ApiDefinitionService {
return request.getId();
}
/**
* 内部构建HashTree 定时任务发起的执行
*
* @param request
* @return
*/
public String run(RunDefinitionRequest request, ApiTestCaseWithBLOBs item) {
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = new ListedHashTree();
try {
MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName());
group.setName(UUID.randomUUID().toString());
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JSONObject element = JSON.parseObject(item.getRequest());
MsScenario scenario = JSONObject.parseObject(item.getRequest(), MsScenario.class);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
new TypeReference<LinkedList<MsTestElement>>() {
});
scenario.setHashTree(elements);
}
if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
scenario.setVariables(variables);
}
group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>();
scenarios.add(scenario);
group.setHashTree(scenarios);
testPlan.getHashTree().add(group);
} catch (Exception ex) {
MSException.throwException(ex.getMessage());
}
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
String runMode = ApiRunMode.DELIMIT.name();
if (StringUtils.isNotBlank(request.getType()) && StringUtils.equals(request.getType(), ApiRunMode.API_PLAN.name())) {
runMode = ApiRunMode.API_PLAN.name();
}
// 调用执行方法
jMeterService.runDefinition(request.getId(), jmeterHashTree, request.getReportId(), runMode);
return request.getId();
}
public void addResult(TestResult res) {
if (!res.getScenarios().isEmpty() && !res.getScenarios().get(0).getRequestResults().isEmpty()) {
cache.put(res.getTestId(), res.getScenarios().get(0).getRequestResults().get(0));

View File

@ -295,7 +295,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
if (level > 8) {
MSException.throwException(Translator.get("node_deep_limit"));
}
if (rootNode.getId().equals("root")) {
if ("root".equals(rootNode.getId())) {
rootPath = "";
}
ApiModule apiDefinitionNode = new ApiModule();

View File

@ -253,7 +253,7 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
if (level > 8) {
MSException.throwException(Translator.get("node_deep_limit"));
}
if (rootNode.getId().equals("root")) {
if ("root".equals(rootNode.getId())) {
rootPath = "";
}
ApiScenarioModule apiScenarioModule = new ApiScenarioModule();

View File

@ -16,11 +16,14 @@ import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.base.mapper.TestPlanApiScenarioMapper;
import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.i18n.Translator;
import io.metersphere.track.service.TestPlanReportService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -28,6 +31,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@ -46,12 +50,16 @@ public class ApiScenarioReportService {
private ApiScenarioMapper apiScenarioMapper;
@Resource
private TestPlanApiScenarioMapper testPlanApiScenarioMapper;
// @Resource
// private TestPlanReportService testPlanReportService;
public ApiScenarioReport complete(TestResult result, String runMode) {
// 更新场景
if (result != null) {
if (StringUtils.equals(runMode, ApiRunMode.SCENARIO_PLAN.name())) {
return updatePlanCase(result);
} else if (StringUtils.equals(runMode, ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) {
return updateSchedulePlanCase(result);
} else {
return updateScenario(result);
}
@ -153,6 +161,65 @@ public class ApiScenarioReportService {
return report;
}
public ApiScenarioReport updateSchedulePlanCase(TestResult result) {
ApiScenarioReport lastReport = null;
List<ScenarioResult> scenarioResultList = result.getScenarios();
List<String> testPlanReportIdList = new ArrayList<>();
for (ScenarioResult scenarioResult : scenarioResultList) {
// 存储场景报告
ApiScenarioReport report = editReport(scenarioResult);
/**
* 测试计划的定时任务场景执行时主键是提前生成的测试报告ID也就是TestResult.id是测试报告ID
* report.getScenarioId中存放的是 TestPlanApiScenario.id:TestPlanReport.id 由于参数限制只得将两个ID拼接起来
* 拆分report.getScenarioId, 查出ScenarioId将真正的场景ID赋值回去
* 同时将testPlanReportID存入集合逻辑走完后更新TestPlanReport
*/
String [] idArr = report.getScenarioId().split(":");
String planScenarioId = null;
if(idArr.length>1){
planScenarioId = idArr[0];
String planReportID = idArr[1];
if(!testPlanReportIdList.contains(planReportID)){
testPlanReportIdList.add(planReportID);
}
}else {
planScenarioId = report.getScenarioId();
}
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(planScenarioId);
report.setScenarioId(testPlanApiScenario.getApiScenarioId());
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
if (scenarioResult.getError() > 0) {
testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name());
} else {
testPlanApiScenario.setLastResult(ScenarioStatus.Success.name());
}
String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError()));
testPlanApiScenario.setPassRate(passRate);
// 报告详情内容
ApiScenarioReportDetail detail = new ApiScenarioReportDetail();
TestResult newResult = createTestResult(result.getTestId(), scenarioResult);
List<ScenarioResult> scenarioResults = new ArrayList();
scenarioResult.setName(report.getScenarioName());
scenarioResults.add(scenarioResult);
newResult.setScenarios(scenarioResults);
detail.setContent(JSON.toJSONString(newResult).getBytes(StandardCharsets.UTF_8));
detail.setReportId(report.getId());
detail.setProjectId(report.getProjectId());
apiScenarioReportDetailMapper.insert(detail);
testPlanApiScenario.setReportId(report.getId());
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
lastReport = report;
}
TestPlanReportService testPlanReportService = CommonBeanFactory.getBean(TestPlanReportService.class);
testPlanReportService.updateReport(testPlanReportIdList,ApiRunMode.SCHEDULE_SCENARIO_PLAN.name(), ReportTriggerMode.SCHEDULE.name());
return lastReport;
}
public ApiScenarioReport updateScenario(TestResult result) {
ApiScenarioReport lastReport = null;
for (ScenarioResult item : result.getScenarios()) {

View File

@ -435,46 +435,11 @@ public class ApiTestCaseService {
public String run(RunCaseRequest request) {
ApiTestCaseWithBLOBs testCaseWithBLOBs = apiTestCaseMapper.selectByPrimaryKey(request.getCaseId());
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (testCaseWithBLOBs != null && StringUtils.isNotEmpty(testCaseWithBLOBs.getRequest())) {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MsTestElement element = mapper.readValue(testCaseWithBLOBs.getRequest(), new TypeReference<MsTestElement>() {
});
if(StringUtils.isBlank(request.getEnvironmentId())){
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
example.createCriteria().andTestPlanIdEqualTo(request.getTestPlanId()).andApiCaseIdEqualTo(request.getCaseId());
List<TestPlanApiCase> list=testPlanApiCaseMapper.selectByExample(example);
request.setEnvironmentId(list.get(0).getEnvironmentId());
element.setName(list.get(0).getId());
}else{
element.setName(request.getCaseId());
}
// 测试计划
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = new ListedHashTree();
// 线程组
MsThreadGroup group = new MsThreadGroup();
group.setLabel(testCaseWithBLOBs.getName());
group.setName(testCaseWithBLOBs.getId());
LinkedList<MsTestElement> hashTrees = new LinkedList<>();
hashTrees.add(element);
group.setHashTree(hashTrees);
testPlan.getHashTree().add(group);
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
ApiTestEnvironmentWithBLOBs environment = environmentService.get(request.getEnvironmentId());
ParameterConfig parameterConfig=new ParameterConfig();
if (environment != null && environment.getConfig() != null) {
parameterConfig.setConfig( JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class));
}
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), parameterConfig);
String runMode = request.getRunMode();
HashTree jmeterHashTree = this.generateHashTree(request,testCaseWithBLOBs);
String runMode = ApiRunMode.DELIMIT.name();
// 调用执行方法
jMeterService.runDefinition(request.getReportId(), jmeterHashTree, request.getReportId(), runMode);
@ -484,6 +449,62 @@ public class ApiTestCaseService {
}
return request.getReportId();
}
public String run(ApiTestCaseWithBLOBs apiCaseBolbs,String id,String debugReportId,String testPlanID,String runMode) {
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (apiCaseBolbs != null && StringUtils.isNotEmpty(apiCaseBolbs.getRequest())) {
try {
ApiTestCase apiTestCase = apiTestCaseMapper.selectByPrimaryKey(apiCaseBolbs.getId());
RunCaseRequest request = new RunCaseRequest();
request.setCaseId(apiTestCase.getId());
request.setTestPlanId(testPlanID);
HashTree jmeterHashTree = this.generateHashTree(request,apiCaseBolbs);
// 调用执行方法
jMeterService.runDefinition(id, jmeterHashTree, debugReportId, runMode);
} catch (Exception ex) {
LogUtil.error(ex.getMessage());
}
}
return id;
}
public HashTree generateHashTree(RunCaseRequest request,ApiTestCaseWithBLOBs testCaseWithBLOBs) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MsTestElement element = mapper.readValue(testCaseWithBLOBs.getRequest(), new TypeReference<MsTestElement>() {
});
if(StringUtils.isBlank(request.getEnvironmentId())){
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
example.createCriteria().andTestPlanIdEqualTo(request.getTestPlanId()).andApiCaseIdEqualTo(request.getCaseId());
List<TestPlanApiCase> list=testPlanApiCaseMapper.selectByExample(example);
request.setEnvironmentId(list.get(0).getEnvironmentId());
element.setName(list.get(0).getId());
}else{
element.setName(request.getCaseId());
}
// 测试计划
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = new ListedHashTree();
// 线程组
MsThreadGroup group = new MsThreadGroup();
group.setLabel(testCaseWithBLOBs.getName());
group.setName(testCaseWithBLOBs.getId());
LinkedList<MsTestElement> hashTrees = new LinkedList<>();
hashTrees.add(element);
group.setHashTree(hashTrees);
testPlan.getHashTree().add(group);
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
ApiTestEnvironmentWithBLOBs environment = environmentService.get(request.getEnvironmentId());
ParameterConfig parameterConfig=new ParameterConfig();
if (environment != null && environment.getConfig() != null) {
parameterConfig.setConfig( JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class));
}
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), parameterConfig);
return jmeterHashTree;
}
public String getExecResult(String id){
String status=apiDefinitionExecResultMapper.selectExecResult(id);

View File

@ -1,10 +1,11 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@ -13,7 +14,5 @@ public class LoadTestWithBLOBs extends LoadTest implements Serializable {
private String advancedConfiguration;
private String schedule;
private static final long serialVersionUID = 1L;
}

View File

@ -19,6 +19,8 @@ public class TestCaseReview implements Serializable {
private Long endTime;
private String projectId;
private String description;
private static final long serialVersionUID = 1L;

View File

@ -563,6 +563,76 @@ public class TestCaseReviewExample {
addCriterion("end_time not between", value1, value2, "endTime");
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 static class Criteria extends GeneratedCriteria {

View File

@ -0,0 +1,37 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
@Data
public class TestPlanReport implements Serializable {
private String id;
private String testPlanId;
private Long createTime;
private Long updateTime;
private String name;
private String status;
private String triggerMode;
private String creator;
private Long startTime;
private Long endTime;
private Boolean isApiCaseExecuting;
private Boolean isScenarioExecuting;
private Boolean isPerformanceExecuting;
private String principal;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,13 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
@Data
public class TestPlanReportData implements Serializable {
private String id;
private String testPlanReportId;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,340 @@
package io.metersphere.base.domain;
import java.util.ArrayList;
import java.util.List;
public class TestPlanReportDataExample {
protected String orderByClause;
protected boolean distinct;
protected List<Criteria> oredCriteria;
public TestPlanReportDataExample() {
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 andTestPlanReportIdIsNull() {
addCriterion("test_plan_report_id is null");
return (Criteria) this;
}
public Criteria andTestPlanReportIdIsNotNull() {
addCriterion("test_plan_report_id is not null");
return (Criteria) this;
}
public Criteria andTestPlanReportIdEqualTo(String value) {
addCriterion("test_plan_report_id =", value, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdNotEqualTo(String value) {
addCriterion("test_plan_report_id <>", value, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdGreaterThan(String value) {
addCriterion("test_plan_report_id >", value, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdGreaterThanOrEqualTo(String value) {
addCriterion("test_plan_report_id >=", value, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdLessThan(String value) {
addCriterion("test_plan_report_id <", value, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdLessThanOrEqualTo(String value) {
addCriterion("test_plan_report_id <=", value, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdLike(String value) {
addCriterion("test_plan_report_id like", value, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdNotLike(String value) {
addCriterion("test_plan_report_id not like", value, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdIn(List<String> values) {
addCriterion("test_plan_report_id in", values, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdNotIn(List<String> values) {
addCriterion("test_plan_report_id not in", values, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdBetween(String value1, String value2) {
addCriterion("test_plan_report_id between", value1, value2, "testPlanReportId");
return (Criteria) this;
}
public Criteria andTestPlanReportIdNotBetween(String value1, String value2) {
addCriterion("test_plan_report_id not between", value1, value2, "testPlanReportId");
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,27 @@
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 TestPlanReportDataWithBLOBs extends TestPlanReportData implements Serializable {
private String executeResult;
private String failurTestCases;
private String moduleExecuteResult;
private String apiCaseInfo;
private String scenarioInfo;
private String performanceInfo;
private String issuesInfo;
private static final long serialVersionUID = 1L;
}

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,6 @@
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.LoadTestWithBLOBs">
<result column="load_configuration" jdbcType="LONGVARCHAR" property="loadConfiguration" />
<result column="advanced_configuration" jdbcType="LONGVARCHAR" property="advancedConfiguration" />
<result column="schedule" jdbcType="LONGVARCHAR" property="schedule" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@ -81,7 +80,7 @@
user_id, num
</sql>
<sql id="Blob_Column_List">
load_configuration, advanced_configuration, schedule
load_configuration, advanced_configuration
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.LoadTestExample" resultMap="ResultMapWithBLOBs">
select
@ -135,13 +134,13 @@
insert into load_test (id, project_id, `name`,
description, create_time, update_time,
`status`, test_resource_pool_id, user_id,
num, load_configuration, advanced_configuration,
schedule)
num, load_configuration, advanced_configuration
)
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
#{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{status,jdbcType=VARCHAR}, #{testResourcePoolId,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR},
#{num,jdbcType=INTEGER}, #{loadConfiguration,jdbcType=LONGVARCHAR}, #{advancedConfiguration,jdbcType=LONGVARCHAR},
#{schedule,jdbcType=LONGVARCHAR})
#{num,jdbcType=INTEGER}, #{loadConfiguration,jdbcType=LONGVARCHAR}, #{advancedConfiguration,jdbcType=LONGVARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.LoadTestWithBLOBs">
insert into load_test
@ -182,9 +181,6 @@
<if test="advancedConfiguration != null">
advanced_configuration,
</if>
<if test="schedule != null">
schedule,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
@ -223,9 +219,6 @@
<if test="advancedConfiguration != null">
#{advancedConfiguration,jdbcType=LONGVARCHAR},
</if>
<if test="schedule != null">
#{schedule,jdbcType=LONGVARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.LoadTestExample" resultType="java.lang.Long">
@ -273,9 +266,6 @@
<if test="record.advancedConfiguration != null">
advanced_configuration = #{record.advancedConfiguration,jdbcType=LONGVARCHAR},
</if>
<if test="record.schedule != null">
schedule = #{record.schedule,jdbcType=LONGVARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -294,8 +284,7 @@
user_id = #{record.userId,jdbcType=VARCHAR},
num = #{record.num,jdbcType=INTEGER},
load_configuration = #{record.loadConfiguration,jdbcType=LONGVARCHAR},
advanced_configuration = #{record.advancedConfiguration,jdbcType=LONGVARCHAR},
schedule = #{record.schedule,jdbcType=LONGVARCHAR}
advanced_configuration = #{record.advancedConfiguration,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -352,9 +341,6 @@
<if test="advancedConfiguration != null">
advanced_configuration = #{advancedConfiguration,jdbcType=LONGVARCHAR},
</if>
<if test="schedule != null">
schedule = #{schedule,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
@ -370,8 +356,7 @@
user_id = #{userId,jdbcType=VARCHAR},
num = #{num,jdbcType=INTEGER},
load_configuration = #{loadConfiguration,jdbcType=LONGVARCHAR},
advanced_configuration = #{advancedConfiguration,jdbcType=LONGVARCHAR},
schedule = #{schedule,jdbcType=LONGVARCHAR}
advanced_configuration = #{advancedConfiguration,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.LoadTest">

View File

@ -9,6 +9,7 @@
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="end_time" jdbcType="BIGINT" property="endTime" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestCaseReview">
<result column="description" jdbcType="LONGVARCHAR" property="description" />
@ -72,7 +73,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id, `name`, creator, `status`, create_time, update_time, end_time
id, `name`, creator, `status`, create_time, update_time, end_time, project_id
</sql>
<sql id="Blob_Column_List">
description
@ -128,10 +129,12 @@
<insert id="insert" parameterType="io.metersphere.base.domain.TestCaseReview">
insert into test_case_review (id, `name`, creator,
`status`, create_time, update_time,
end_time, description)
end_time, project_id, description
)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{creator,jdbcType=VARCHAR},
#{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{endTime,jdbcType=BIGINT}, #{description,jdbcType=LONGVARCHAR})
#{endTime,jdbcType=BIGINT}, #{projectId,jdbcType=VARCHAR}, #{description,jdbcType=LONGVARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestCaseReview">
insert into test_case_review
@ -157,6 +160,9 @@
<if test="endTime != null">
end_time,
</if>
<if test="projectId != null">
project_id,
</if>
<if test="description != null">
description,
</if>
@ -183,6 +189,9 @@
<if test="endTime != null">
#{endTime,jdbcType=BIGINT},
</if>
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
</if>
<if test="description != null">
#{description,jdbcType=LONGVARCHAR},
</if>
@ -218,6 +227,9 @@
<if test="record.endTime != null">
end_time = #{record.endTime,jdbcType=BIGINT},
</if>
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
</if>
<if test="record.description != null">
description = #{record.description,jdbcType=LONGVARCHAR},
</if>
@ -235,6 +247,7 @@
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
end_time = #{record.endTime,jdbcType=BIGINT},
project_id = #{record.projectId,jdbcType=VARCHAR},
description = #{record.description,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -248,7 +261,8 @@
`status` = #{record.status,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
end_time = #{record.endTime,jdbcType=BIGINT}
end_time = #{record.endTime,jdbcType=BIGINT},
project_id = #{record.projectId,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -274,6 +288,9 @@
<if test="endTime != null">
end_time = #{endTime,jdbcType=BIGINT},
</if>
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
</if>
<if test="description != null">
description = #{description,jdbcType=LONGVARCHAR},
</if>
@ -288,6 +305,7 @@
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
end_time = #{endTime,jdbcType=BIGINT},
project_id = #{projectId,jdbcType=VARCHAR},
description = #{description,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
@ -298,7 +316,8 @@
`status` = #{status,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
end_time = #{endTime,jdbcType=BIGINT}
end_time = #{endTime,jdbcType=BIGINT},
project_id = #{projectId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

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

View File

@ -0,0 +1,312 @@
<?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.TestPlanReportDataMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.TestPlanReportData">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="test_plan_report_id" jdbcType="VARCHAR" property="testPlanReportId" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.TestPlanReportDataWithBLOBs">
<result column="execute_result" jdbcType="LONGVARCHAR" property="executeResult" />
<result column="failur_test_cases" jdbcType="LONGVARCHAR" property="failurTestCases" />
<result column="module_execute_result" jdbcType="LONGVARCHAR" property="moduleExecuteResult" />
<result column="api_case_info" jdbcType="LONGVARCHAR" property="apiCaseInfo" />
<result column="scenario_info" jdbcType="LONGVARCHAR" property="scenarioInfo" />
<result column="performance_info" jdbcType="LONGVARCHAR" property="performanceInfo" />
<result column="issues_info" jdbcType="LONGVARCHAR" property="issuesInfo" />
</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, test_plan_report_id
</sql>
<sql id="Blob_Column_List">
execute_result, failur_test_cases, module_execute_result, api_case_info, scenario_info,
performance_info, issues_info
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.TestPlanReportDataExample" resultMap="ResultMapWithBLOBs">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from test_plan_report_data
<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.TestPlanReportDataExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from test_plan_report_data
<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 test_plan_report_data
where id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from test_plan_report_data
where id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.TestPlanReportDataExample">
delete from test_plan_report_data
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.TestPlanReportDataWithBLOBs">
insert into test_plan_report_data (id, test_plan_report_id, execute_result,
failur_test_cases, module_execute_result,
api_case_info, scenario_info, performance_info,
issues_info)
values (#{id,jdbcType=VARCHAR}, #{testPlanReportId,jdbcType=VARCHAR}, #{executeResult,jdbcType=LONGVARCHAR},
#{failurTestCases,jdbcType=LONGVARCHAR}, #{moduleExecuteResult,jdbcType=LONGVARCHAR},
#{apiCaseInfo,jdbcType=LONGVARCHAR}, #{scenarioInfo,jdbcType=LONGVARCHAR}, #{performanceInfo,jdbcType=LONGVARCHAR},
#{issuesInfo,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanReportDataWithBLOBs">
insert into test_plan_report_data
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="testPlanReportId != null">
test_plan_report_id,
</if>
<if test="executeResult != null">
execute_result,
</if>
<if test="failurTestCases != null">
failur_test_cases,
</if>
<if test="moduleExecuteResult != null">
module_execute_result,
</if>
<if test="apiCaseInfo != null">
api_case_info,
</if>
<if test="scenarioInfo != null">
scenario_info,
</if>
<if test="performanceInfo != null">
performance_info,
</if>
<if test="issuesInfo != null">
issues_info,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="testPlanReportId != null">
#{testPlanReportId,jdbcType=VARCHAR},
</if>
<if test="executeResult != null">
#{executeResult,jdbcType=LONGVARCHAR},
</if>
<if test="failurTestCases != null">
#{failurTestCases,jdbcType=LONGVARCHAR},
</if>
<if test="moduleExecuteResult != null">
#{moduleExecuteResult,jdbcType=LONGVARCHAR},
</if>
<if test="apiCaseInfo != null">
#{apiCaseInfo,jdbcType=LONGVARCHAR},
</if>
<if test="scenarioInfo != null">
#{scenarioInfo,jdbcType=LONGVARCHAR},
</if>
<if test="performanceInfo != null">
#{performanceInfo,jdbcType=LONGVARCHAR},
</if>
<if test="issuesInfo != null">
#{issuesInfo,jdbcType=LONGVARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.TestPlanReportDataExample" resultType="java.lang.Long">
select count(*) from test_plan_report_data
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update test_plan_report_data
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.testPlanReportId != null">
test_plan_report_id = #{record.testPlanReportId,jdbcType=VARCHAR},
</if>
<if test="record.executeResult != null">
execute_result = #{record.executeResult,jdbcType=LONGVARCHAR},
</if>
<if test="record.failurTestCases != null">
failur_test_cases = #{record.failurTestCases,jdbcType=LONGVARCHAR},
</if>
<if test="record.moduleExecuteResult != null">
module_execute_result = #{record.moduleExecuteResult,jdbcType=LONGVARCHAR},
</if>
<if test="record.apiCaseInfo != null">
api_case_info = #{record.apiCaseInfo,jdbcType=LONGVARCHAR},
</if>
<if test="record.scenarioInfo != null">
scenario_info = #{record.scenarioInfo,jdbcType=LONGVARCHAR},
</if>
<if test="record.performanceInfo != null">
performance_info = #{record.performanceInfo,jdbcType=LONGVARCHAR},
</if>
<if test="record.issuesInfo != null">
issues_info = #{record.issuesInfo,jdbcType=LONGVARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update test_plan_report_data
set id = #{record.id,jdbcType=VARCHAR},
test_plan_report_id = #{record.testPlanReportId,jdbcType=VARCHAR},
execute_result = #{record.executeResult,jdbcType=LONGVARCHAR},
failur_test_cases = #{record.failurTestCases,jdbcType=LONGVARCHAR},
module_execute_result = #{record.moduleExecuteResult,jdbcType=LONGVARCHAR},
api_case_info = #{record.apiCaseInfo,jdbcType=LONGVARCHAR},
scenario_info = #{record.scenarioInfo,jdbcType=LONGVARCHAR},
performance_info = #{record.performanceInfo,jdbcType=LONGVARCHAR},
issues_info = #{record.issuesInfo,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update test_plan_report_data
set id = #{record.id,jdbcType=VARCHAR},
test_plan_report_id = #{record.testPlanReportId,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.TestPlanReportDataWithBLOBs">
update test_plan_report_data
<set>
<if test="testPlanReportId != null">
test_plan_report_id = #{testPlanReportId,jdbcType=VARCHAR},
</if>
<if test="executeResult != null">
execute_result = #{executeResult,jdbcType=LONGVARCHAR},
</if>
<if test="failurTestCases != null">
failur_test_cases = #{failurTestCases,jdbcType=LONGVARCHAR},
</if>
<if test="moduleExecuteResult != null">
module_execute_result = #{moduleExecuteResult,jdbcType=LONGVARCHAR},
</if>
<if test="apiCaseInfo != null">
api_case_info = #{apiCaseInfo,jdbcType=LONGVARCHAR},
</if>
<if test="scenarioInfo != null">
scenario_info = #{scenarioInfo,jdbcType=LONGVARCHAR},
</if>
<if test="performanceInfo != null">
performance_info = #{performanceInfo,jdbcType=LONGVARCHAR},
</if>
<if test="issuesInfo != null">
issues_info = #{issuesInfo,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.TestPlanReportDataWithBLOBs">
update test_plan_report_data
set test_plan_report_id = #{testPlanReportId,jdbcType=VARCHAR},
execute_result = #{executeResult,jdbcType=LONGVARCHAR},
failur_test_cases = #{failurTestCases,jdbcType=LONGVARCHAR},
module_execute_result = #{moduleExecuteResult,jdbcType=LONGVARCHAR},
api_case_info = #{apiCaseInfo,jdbcType=LONGVARCHAR},
scenario_info = #{scenarioInfo,jdbcType=LONGVARCHAR},
performance_info = #{performanceInfo,jdbcType=LONGVARCHAR},
issues_info = #{issuesInfo,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.TestPlanReportData">
update test_plan_report_data
set test_plan_report_id = #{testPlanReportId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

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

View File

@ -0,0 +1,354 @@
<?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.TestPlanReportMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.TestPlanReport">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="test_plan_id" jdbcType="VARCHAR" property="testPlanId" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="trigger_mode" jdbcType="VARCHAR" property="triggerMode" />
<result column="creator" jdbcType="VARCHAR" property="creator" />
<result column="start_time" jdbcType="BIGINT" property="startTime" />
<result column="end_time" jdbcType="BIGINT" property="endTime" />
<result column="is_api_case_executing" jdbcType="BIT" property="isApiCaseExecuting" />
<result column="is_scenario_executing" jdbcType="BIT" property="isScenarioExecuting" />
<result column="is_performance_executing" jdbcType="BIT" property="isPerformanceExecuting" />
<result column="principal" jdbcType="VARCHAR" property="principal" />
</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, test_plan_id, create_time, update_time, `name`, `status`, trigger_mode, creator,
start_time, end_time, is_api_case_executing, is_scenario_executing, is_performance_executing,
principal
</sql>
<select id="selectByExample" parameterType="io.metersphere.base.domain.TestPlanReportExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from test_plan_report
<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="BaseResultMap">
select
<include refid="Base_Column_List" />
from test_plan_report
where id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from test_plan_report
where id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.TestPlanReportExample">
delete from test_plan_report
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.TestPlanReport">
insert into test_plan_report (id, test_plan_id, create_time,
update_time, `name`, `status`,
trigger_mode, creator, start_time,
end_time, is_api_case_executing, is_scenario_executing,
is_performance_executing, principal)
values (#{id,jdbcType=VARCHAR}, #{testPlanId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
#{updateTime,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
#{triggerMode,jdbcType=VARCHAR}, #{creator,jdbcType=VARCHAR}, #{startTime,jdbcType=BIGINT},
#{endTime,jdbcType=BIGINT}, #{isApiCaseExecuting,jdbcType=BIT}, #{isScenarioExecuting,jdbcType=BIT},
#{isPerformanceExecuting,jdbcType=BIT}, #{principal,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.TestPlanReport">
insert into test_plan_report
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="testPlanId != null">
test_plan_id,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateTime != null">
update_time,
</if>
<if test="name != null">
`name`,
</if>
<if test="status != null">
`status`,
</if>
<if test="triggerMode != null">
trigger_mode,
</if>
<if test="creator != null">
creator,
</if>
<if test="startTime != null">
start_time,
</if>
<if test="endTime != null">
end_time,
</if>
<if test="isApiCaseExecuting != null">
is_api_case_executing,
</if>
<if test="isScenarioExecuting != null">
is_scenario_executing,
</if>
<if test="isPerformanceExecuting != null">
is_performance_executing,
</if>
<if test="principal != null">
principal,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="testPlanId != null">
#{testPlanId,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=BIGINT},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=VARCHAR},
</if>
<if test="triggerMode != null">
#{triggerMode,jdbcType=VARCHAR},
</if>
<if test="creator != null">
#{creator,jdbcType=VARCHAR},
</if>
<if test="startTime != null">
#{startTime,jdbcType=BIGINT},
</if>
<if test="endTime != null">
#{endTime,jdbcType=BIGINT},
</if>
<if test="isApiCaseExecuting != null">
#{isApiCaseExecuting,jdbcType=BIT},
</if>
<if test="isScenarioExecuting != null">
#{isScenarioExecuting,jdbcType=BIT},
</if>
<if test="isPerformanceExecuting != null">
#{isPerformanceExecuting,jdbcType=BIT},
</if>
<if test="principal != null">
#{principal,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.TestPlanReportExample" resultType="java.lang.Long">
select count(*) from test_plan_report
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update test_plan_report
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.testPlanId != null">
test_plan_id = #{record.testPlanId,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.name != null">
`name` = #{record.name,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
`status` = #{record.status,jdbcType=VARCHAR},
</if>
<if test="record.triggerMode != null">
trigger_mode = #{record.triggerMode,jdbcType=VARCHAR},
</if>
<if test="record.creator != null">
creator = #{record.creator,jdbcType=VARCHAR},
</if>
<if test="record.startTime != null">
start_time = #{record.startTime,jdbcType=BIGINT},
</if>
<if test="record.endTime != null">
end_time = #{record.endTime,jdbcType=BIGINT},
</if>
<if test="record.isApiCaseExecuting != null">
is_api_case_executing = #{record.isApiCaseExecuting,jdbcType=BIT},
</if>
<if test="record.isScenarioExecuting != null">
is_scenario_executing = #{record.isScenarioExecuting,jdbcType=BIT},
</if>
<if test="record.isPerformanceExecuting != null">
is_performance_executing = #{record.isPerformanceExecuting,jdbcType=BIT},
</if>
<if test="record.principal != null">
principal = #{record.principal,jdbcType=VARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update test_plan_report
set id = #{record.id,jdbcType=VARCHAR},
test_plan_id = #{record.testPlanId,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
`name` = #{record.name,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
trigger_mode = #{record.triggerMode,jdbcType=VARCHAR},
creator = #{record.creator,jdbcType=VARCHAR},
start_time = #{record.startTime,jdbcType=BIGINT},
end_time = #{record.endTime,jdbcType=BIGINT},
is_api_case_executing = #{record.isApiCaseExecuting,jdbcType=BIT},
is_scenario_executing = #{record.isScenarioExecuting,jdbcType=BIT},
is_performance_executing = #{record.isPerformanceExecuting,jdbcType=BIT},
principal = #{record.principal,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.TestPlanReport">
update test_plan_report
<set>
<if test="testPlanId != null">
test_plan_id = #{testPlanId,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="name != null">
`name` = #{name,jdbcType=VARCHAR},
</if>
<if test="status != null">
`status` = #{status,jdbcType=VARCHAR},
</if>
<if test="triggerMode != null">
trigger_mode = #{triggerMode,jdbcType=VARCHAR},
</if>
<if test="creator != null">
creator = #{creator,jdbcType=VARCHAR},
</if>
<if test="startTime != null">
start_time = #{startTime,jdbcType=BIGINT},
</if>
<if test="endTime != null">
end_time = #{endTime,jdbcType=BIGINT},
</if>
<if test="isApiCaseExecuting != null">
is_api_case_executing = #{isApiCaseExecuting,jdbcType=BIT},
</if>
<if test="isScenarioExecuting != null">
is_scenario_executing = #{isScenarioExecuting,jdbcType=BIT},
</if>
<if test="isPerformanceExecuting != null">
is_performance_executing = #{isPerformanceExecuting,jdbcType=BIT},
</if>
<if test="principal != null">
principal = #{principal,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.TestPlanReport">
update test_plan_report
set test_plan_id = #{testPlanId,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
`name` = #{name,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
trigger_mode = #{triggerMode,jdbcType=VARCHAR},
creator = #{creator,jdbcType=VARCHAR},
start_time = #{startTime,jdbcType=BIGINT},
end_time = #{endTime,jdbcType=BIGINT},
is_api_case_executing = #{isApiCaseExecuting,jdbcType=BIT},
is_scenario_executing = #{isScenarioExecuting,jdbcType=BIT},
is_performance_executing = #{isPerformanceExecuting,jdbcType=BIT},
principal = #{principal,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -6,17 +6,16 @@
parameterType="io.metersphere.track.request.testreview.QueryCaseReviewRequest">
select distinct test_case_review.id, test_case_review.name, test_case_review.creator, test_case_review.status,
test_case_review.create_time, test_case_review.update_time, test_case_review.end_time,
test_case_review.description, user.name as creatorName
from test_case_review join test_case_review_project on test_case_review.id = test_case_review_project.review_id
join project on test_case_review_project.project_id = project.id
left join user on test_case_review.creator = user.id
test_case_review.description, user.name as creatorName, project.name as projectName, test_case_review.project_id
from test_case_review
join project on project.id = test_case_review.project_id
left join user on test_case_review.creator = user.id
<where>
<if test="request.name != null">
and test_case_review.name like CONCAT('%', #{request.name},'%')
</if>
and project.workspace_id = #{request.workspaceId}
<if test="request.projectId != null">
and test_case_review_project.project_id = #{request.projectId}
and test_case_review.project_id = #{request.projectId}
</if>
</where>
<if test="request.orders != null and request.orders.size() > 0">
@ -30,13 +29,10 @@
<select id="listByWorkspaceId" resultType="io.metersphere.track.dto.TestCaseReviewDTO"
parameterType="io.metersphere.track.request.testreview.QueryCaseReviewRequest">
select distinct test_case_review.*
from test_case_review, project, test_case_review_project, test_case_review_users
from test_case_review, test_case_review_users
<where>
test_case_review.id = test_case_review_project.review_id
and test_case_review_project.project_id = project.id
and project.workspace_id = #{workspaceId}
<if test="projectId != null">
and test_case_review_project.project_id = #{projectId}
and test_case_review.project_id = #{projectId}
</if>
and (
(test_case_review_users.review_id = test_case_review.id
@ -48,9 +44,8 @@
</select>
<select id="listRelate" resultType="io.metersphere.track.dto.TestReviewDTOWithMetric">
select distinct test_case_review.* from test_case_review
inner join test_case_review_project on test_case_review.id = test_case_review_project.review_id
inner join project on project.id = test_case_review_project.project_id
select distinct test_case_review.*, project.name as projectName from test_case_review
inner join project on project.id = test_case_review.project_id
inner join test_case_review_users on test_case_review_users.review_id = test_case_review.id
<where>
project.workspace_id = #{request.workspaceId}
@ -58,7 +53,7 @@
and test_case_review_users.user_id = #{request.reviewerId}
</if>
<if test="request.projectId != null">
and test_case_review_project.project_id = #{request.projectId}
and test_case_review.project_id = #{request.projectId}
</if>
<if test="request.creator != null">
and (test_case_review.creator = #{request.creator}
@ -75,15 +70,24 @@
order by test_case_review.update_time desc
</select>
<select id="checkIsHave" resultType="int">
SELECT COUNT(1)
select sum(c) from (
SELECT COUNT(1) as c
FROM project, test_case_review_project
WHERE project.id = test_case_review_project.project_id
WHERE project.id = test_case_review_project.project_id AND test_case_review_project.review_id = #{reviewId}
<if test="workspaceIds != null and workspaceIds.size() > 0">
AND project.workspace_id IN
<foreach collection="workspaceIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</if>
AND test_case_review_project.review_id = #{reviewId}
union
select count(1) as c from test_case_review, project
WHERE project_id = project.id AND test_case_review.id = #{reviewId}
<if test="workspaceIds != null and workspaceIds.size() > 0">
AND project.workspace_id IN
<foreach collection="workspaceIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</if>) as temp
</select>
</mapper>

View File

@ -17,4 +17,6 @@ public interface ExtTestPlanApiCaseMapper {
List<String> getIdsByPlanId(String planId);
List<String> getNotRelevanceCaseIds(@Param("planId")String planId, @Param("relevanceProjectIds")List<String> relevanceProjectIds);
List<String> getStatusByTestPlanId(String id);
}

View File

@ -125,5 +125,8 @@
</if>
where t.test_plan_id = #{planId}
</select>
<select id="getStatusByTestPlanId" resultType="java.lang.String">
SELECT `status` FROM test_plan_api_case WHERE test_plan_id = #{0}
</select>
</mapper>

View File

@ -9,4 +9,5 @@ public interface ExtTestPlanLoadCaseMapper {
List<String> selectIdsNotInPlan(@Param("projectId") String projectId, @Param("planId") String planId);
List<TestPlanLoadCaseDTO> selectTestPlanLoadCaseList(@Param("planId") String planId, @Param("projectId") String projectId);
void updateCaseStatus(@Param("reportId") String reportId, @Param("status") String status);
}

View File

@ -1,6 +1,9 @@
<?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.ext.ExtTestPlanLoadCaseMapper">
<update id="updateCaseStatus">
update test_plan_load_case tplc set status = #{status} where tplc.load_report_id = #{reportId}
</update>
<select id="selectIdsNotInPlan" resultType="java.lang.String">
select load_test.id

View File

@ -26,4 +26,10 @@ public interface ExtTestPlanMapper {
List<TestPlanDTO> selectTestPlanByRelevancy(@Param("request") QueryTestPlanRequest params);
int checkIsHave(@Param("planId") String planId, @Param("workspaceIds") Set<String> workspaceIds);
String findTestProjectNameByTestPlanID(String testPlanId);
String findScheduleCreateUserById(String testPlanId);
List<String> findIdByPerformanceReportId(String reportId);
}

View File

@ -98,8 +98,9 @@
<select id="list" resultType="io.metersphere.track.dto.TestPlanDTOWithMetric"
parameterType="io.metersphere.track.request.testcase.QueryTestPlanRequest">
select DISTINCT test_plan.*, user.name as user_name, project.name as projectName from test_plan
select DISTINCT test_plan.*, user.name as user_name, project.name as projectName,schedule.id as scheduleId from test_plan
LEFT JOIN user ON user.id = test_plan.principal
LEFT JOIN schedule ON schedule.resource_id = test_plan.id
JOIN project on project.id = test_plan.project_id
<where>
<if test="request.combine != null">
@ -222,4 +223,19 @@
</if>
</where>
</select>
<select id="findTestProjectNameByTestPlanID" resultType="java.lang.String">
SELECT p.name FROM TEST_PLAN tp INNER JOIN project p ON p.id =tp.project_id
WHERE tp.id = #{0} limit 1;
</select>
<select id="findScheduleCreateUserById" resultType="java.lang.String">
SELECT user_id FROM `schedule`
WHERE resource_id = #{0}
limit 1;
</select>
<select id="findIdByPerformanceReportId" resultType="java.lang.String">
SELECT report.id FROM test_plan_report report INNER JOIN test_plan_report_data reportData ON report.id = reportData.test_plan_report_id
WHERE reportData.performance_info like CONCAT('%', #{0}'%')
</select>
</mapper>

View File

@ -0,0 +1,16 @@
package io.metersphere.base.mapper.ext;
import io.metersphere.track.dto.TestPlanReportDTO;
import io.metersphere.track.request.report.QueryTestPlanReportRequest;
import org.springframework.data.repository.query.Param;
import java.util.List;
/**
* @author song.tianyang
* @Date 2021/1/8 4:58 下午
* @Description
*/
public interface ExtTestPlanReportMapper {
public List<TestPlanReportDTO> list(@Param("request")QueryTestPlanReportRequest request);
}

View File

@ -0,0 +1,37 @@
<?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.ext.ExtTestPlanReportMapper">
<select id="list" resultType="io.metersphere.track.dto.TestPlanReportDTO"
parameterType="io.metersphere.track.request.report.QueryTestPlanReportRequest">
SELECT tpr.id AS id, tpr.`name` AS `name`, tp.`name` AS testPlanName, tpr.creator AS creator, tpr.create_time AS createTime,tpr.trigger_Mode AS triggerMode
FROM test_plan tp
INNER JOIN test_plan_report tpr on tp.id = tpr.test_plan_id
<where>
<if test="name != null">
and tpr.name like CONCAT('%', #{name},'%')
</if>
<if test="projectId != null">
AND tp.project_id = #{projectId}
</if>
<if test="testPlanName != null">
AND tp.name like CONCAT('%', #{testPlanName},'%')
</if>
<if test="creator != null">
AND tpr.creator = #{creator}
</if>
</where>
<if test="orders != null and orders.size() > 0">
order by
<foreach collection="orders" separator="," item="order">
<if test="order.name == 'test_plan_name'">
tp.name ${order.type}
</if>
<if test="order.name != 'test_plan_name'">
tpr.${order.name} ${order.type}
</if>
</foreach>
</if>
</select>
</mapper>

View File

@ -202,11 +202,10 @@
<select id="findRelateTestReviewId" resultType="java.lang.String">
select distinct test_case_review_test_case.review_id from test_case_review_test_case
inner join test_case_review on test_case_review_test_case.review_id = test_case_review.id
inner join test_case_review_project on test_case_review_project.review_id = test_case_review.id
inner join project on project.id = test_case_review_project.project_id
inner join project on project.id = test_case_review.project_id
where test_case_review_test_case.review_id = #{userId}
and project.workspace_id = #{workspaceId}
and test_case_review_project.project_id = #{projectId}
and test_case_review.project_id = #{projectId}
</select>
<select id="listTestCaseByProjectIds" resultType="io.metersphere.track.dto.TestReviewCaseDTO">
select distinct * from test_case_review_test_case, test_case

View File

@ -1,5 +1,5 @@
package io.metersphere.commons.constants;
public enum ApiRunMode {
RUN, DEBUG,DELIMIT,SCENARIO, API_PLAN, SCENARIO_PLAN,API
RUN, DEBUG,DELIMIT,SCENARIO, API_PLAN, SCENARIO_PLAN,API,SCHEDULE_API_PLAN,SCHEDULE_SCENARIO_PLAN,SCHEDULE_PERFORMANCE_TEST
}

View File

@ -1,5 +1,11 @@
package io.metersphere.commons.constants;
public enum ReportTriggerMode {
MANUAL, SCHEDULE, API
MANUAL,
SCHEDULE,
API,
/**
* 性能测试用例执行触发报告
*/
CASE
}

View File

@ -5,6 +5,7 @@ import io.metersphere.Application;
import io.metersphere.base.domain.LoadTestReport;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.config.KafkaProperties;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.reflections8.Reflections;
import org.springframework.kafka.annotation.KafkaListener;
@ -21,6 +22,8 @@ public class LoadTestConsumer {
LoadTestReport loadTestReport = JSON.parseObject(record.value(), LoadTestReport.class);
Reflections reflections = new Reflections(Application.class);
Set<Class<? extends LoadTestFinishEvent>> subTypes = reflections.getSubTypesOf(LoadTestFinishEvent.class);
LogUtil.info("Execute Over: LoadTestConsumer");
System.out.println("Execute Over: LoadTestConsumer");
subTypes.forEach(s -> {
try {
CommonBeanFactory.getBean(s).execute(loadTestReport);

View File

@ -2,46 +2,51 @@ package io.metersphere.job.sechedule;
import io.metersphere.api.dto.automation.ExecuteType;
import io.metersphere.api.dto.automation.RunScenarioRequest;
import io.metersphere.api.dto.automation.SchedulePlanScenarioExecuteRequest;
import io.metersphere.api.dto.definition.RunCaseRequest;
import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.api.service.ApiTestCaseService;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.domain.TestPlanApiCase;
import io.metersphere.base.domain.TestPlanApiScenario;
import io.metersphere.base.domain.*;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.constants.ScheduleGroup;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.track.dto.TestPlanLoadCaseDTO;
import io.metersphere.track.request.testplan.LoadCaseRequest;
import io.metersphere.track.request.testplan.RunTestPlanRequest;
import io.metersphere.track.service.TestPlanApiCaseService;
import io.metersphere.track.service.TestPlanScenarioCaseService;
import io.metersphere.track.service.*;
import org.python.antlr.ast.Str;
import org.quartz.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 情景测试Job
*
* @author song.tianyang
* @Date 2020/12/22 2:59 下午
* @Description
*/
public class TestPlanTestJob extends MsScheduleJob {
private String projectID;
private List<String> scenarioIds;
private List<String> apiTestCaseIds;
private List<String> performanceIds;
public class TestPlanTestJob extends MsScheduleJob {
private String projectID;
private Map<String,String> planScenarioIdMap;
private Map<String,String> apiTestCaseIdMap;
private Map<String,String> performanceIdMap;
private ApiAutomationService apiAutomationService;
private PerformanceTestService performanceTestService;
private TestPlanScenarioCaseService testPlanScenarioCaseService;
private TestPlanApiCaseService testPlanApiCaseService;
private ApiTestCaseService apiTestCaseService;
private ApiDefinitionService apiDefinitionService;
private TestPlanReportService testPlanReportService;
private TestPlanLoadCaseService testPlanLoadCaseService;
public TestPlanTestJob() {
this.apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
@ -49,11 +54,13 @@ public class TestPlanTestJob extends MsScheduleJob {
this.testPlanScenarioCaseService = CommonBeanFactory.getBean(TestPlanScenarioCaseService.class);
this.testPlanApiCaseService = CommonBeanFactory.getBean(TestPlanApiCaseService.class);
this.apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
this.testPlanReportService = CommonBeanFactory.getBean(TestPlanReportService.class);
this.testPlanLoadCaseService = CommonBeanFactory.getBean(TestPlanLoadCaseService.class);
}
/**
* 情景部分的准备工作
*
* @param context
* @throws JobExecutionException
*/
@ -62,21 +69,31 @@ public class TestPlanTestJob extends MsScheduleJob {
JobKey jobKey = context.getTrigger().getJobKey();
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
this.resourceId = jobDataMap.getString("resourceId");
this.userId = jobDataMap.getString("userId");
this.expression = jobDataMap.getString("expression");
this.projectID = jobDataMap.getString("projectId");
scenarioIds = new ArrayList<>();
String testPlanID = jobDataMap.getString("resourceId");
List<TestPlanApiScenario> testPlanApiScenarioList = testPlanScenarioCaseService.getCasesByPlanId(testPlanID);
for (TestPlanApiScenario model:
testPlanApiScenarioList) {
scenarioIds.add(model.getApiScenarioId());
planScenarioIdMap = new LinkedHashMap<>();
apiTestCaseIdMap = new LinkedHashMap<>();
performanceIdMap = new LinkedHashMap<>();
List<TestPlanApiScenario> testPlanApiScenarioList = testPlanScenarioCaseService.getCasesByPlanId(this.resourceId);
for (TestPlanApiScenario model :testPlanApiScenarioList) {
planScenarioIdMap.put(model.getApiScenarioId(),model.getId());
}
List<TestPlanApiCase> testPlanApiCaseList = testPlanApiCaseService.getCasesByPlanId(testPlanID);
List<TestPlanApiCase> testPlanApiCaseList = testPlanApiCaseService.getCasesByPlanId(this.resourceId);
for (TestPlanApiCase model :
testPlanApiCaseList) {
apiTestCaseIds.add(model.getApiCaseId());
apiTestCaseIdMap.put(model.getApiCaseId(),model.getId());
}
LoadCaseRequest loadCaseRequest = new LoadCaseRequest();
loadCaseRequest.setTestPlanId(this.resourceId);
loadCaseRequest.setProjectId(this.projectID);
List<TestPlanLoadCaseDTO> testPlanLoadCaseDTOList = testPlanLoadCaseService.list(loadCaseRequest);
for (TestPlanLoadCaseDTO dto : testPlanLoadCaseDTOList) {
performanceIdMap.put(dto.getId(),dto.getLoadCaseId());
}
businessExecute(context);
@ -85,39 +102,66 @@ public class TestPlanTestJob extends MsScheduleJob {
@Override
void businessExecute(JobExecutionContext context) {
LogUtil.info("-------------- start testplan schedule ----------");
//首先创建testPlanReport然后返回的ID重新赋值为resourceID作为后续的参数
TestPlanReport testPlanReport = testPlanReportService.genTestPlanReport(this.resourceId,this.userId,ReportTriggerMode.SCHEDULE.name());
//执行接口案例任务
for (String apiCaseID:apiTestCaseIds) {
for (Map.Entry<String,String> entry: this.apiTestCaseIdMap.entrySet()) {
String apiCaseID = entry.getKey();
String planCaseID = entry.getValue();
ApiTestCaseWithBLOBs blobs = apiTestCaseService.get(apiCaseID);
String caseReportID = UUID.randomUUID().toString();
RunDefinitionRequest apiCaseReqeust = new RunDefinitionRequest();
apiCaseReqeust.setId(apiCaseID);
apiCaseReqeust.setReportId(caseReportID);
apiCaseReqeust.setProjectId(projectID);
apiCaseReqeust.setExecuteType(ExecuteType.Saved.name());
apiCaseReqeust.setType(ApiRunMode.API_PLAN.name());
apiDefinitionService.run(apiCaseReqeust,blobs);
//需要更新这里来保证PlanCase的状态能正常更改
apiTestCaseService.run(blobs,UUID.randomUUID().toString(),testPlanReport.getId(),this.resourceId,ApiRunMode.SCHEDULE_API_PLAN.name());
}
LogUtil.info("-------------- testplan schedule ---------- api case over -----------------");
//执行场景执行任务
RunScenarioRequest scenarioRequest = new RunScenarioRequest();
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
String senarionReportID = UUID.randomUUID().toString();
scenarioRequest.setId(senarionReportID);
scenarioRequest.setReportId(senarionReportID);
scenarioRequest.setProjectId(projectID);
scenarioRequest.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
scenarioRequest.setExecuteType(ExecuteType.Saved.name());
scenarioRequest.setScenarioIds(this.scenarioIds);
Map<String, Map<String,String>> testPlanScenarioIdMap = new HashMap<>();
testPlanScenarioIdMap.put(resourceId, this.planScenarioIdMap);
scenarioRequest.setTestPlanScenarioIDMap(testPlanScenarioIdMap);
scenarioRequest.setReportUserID(this.userId);
scenarioRequest.setRunMode(ApiRunMode.SCENARIO_PLAN.name());
String reportID = apiAutomationService.run(scenarioRequest);
scenarioRequest.setTestPlanID(this.resourceId);
scenarioRequest.setRunMode(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name());
scenarioRequest.setTestPlanReportId(testPlanReport.getId());
apiAutomationService.run(scenarioRequest);
LogUtil.info("-------------- testplan schedule ---------- scenario case over -----------------");
//执行性能测试任务 --- 保留待功能实现后再继续
// RunTestPlanRequest performanceRequest = new RunTestPlanRequest();
// performanceRequest.setId(resourceId);
// performanceRequest.setUserId(userId);
// performanceRequest.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
// performanceTestService.run(performanceRequest);
//执行性能测试任务
List<String> performaneReportIDList = new ArrayList<>();
for (Map.Entry<String,String> entry: this.performanceIdMap.entrySet()) {
String id = entry.getKey();
String caseID = entry.getValue();
RunTestPlanRequest performanceRequest = new RunTestPlanRequest();
performanceRequest.setId(caseID);
performanceRequest.setTestPlanLoadId(caseID);
performanceRequest.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
String reportId = null;
try {
reportId = performanceTestService.run(performanceRequest);
if(reportId!=null){
performaneReportIDList.add(reportId);
TestPlanLoadCase testPlanLoadCase = new TestPlanLoadCase();
testPlanLoadCase.setId(performanceRequest.getTestPlanLoadId());
testPlanLoadCase.setLoadReportId(reportId);
testPlanLoadCaseService.update(testPlanLoadCase);
}
}catch (Exception e){
e.printStackTrace();
}
}
if(!performaneReportIDList.isEmpty()){
//性能测试时保存性能测试报告ID在结果返回时用于捕捉并进行
testPlanReportService.updatePerformanceInfo(testPlanReport,performaneReportIDList,ReportTriggerMode.SCHEDULE.name());
}
}
public static JobKey getJobKey(String testId) {

View File

@ -5,6 +5,7 @@ import io.metersphere.commons.constants.NoticeConstants;
import io.metersphere.commons.constants.PerformanceTestStatus;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.consumer.LoadTestFinishEvent;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.i18n.Translator;
import io.metersphere.notice.sender.NoticeModel;
@ -70,6 +71,7 @@ public class PerformanceNoticeEvent implements LoadTestFinishEvent {
@Override
public void execute(LoadTestReport loadTestReport) {
LogUtil.info("PerformanceNoticeEvent OVER:" + loadTestReport.getTriggerMode()+";"+loadTestReport.getStatus());
if (StringUtils.equals(ReportTriggerMode.API.name(), loadTestReport.getTriggerMode())
|| StringUtils.equals(ReportTriggerMode.SCHEDULE.name(), loadTestReport.getTriggerMode())) {
if (StringUtils.equalsAny(loadTestReport.getStatus(),

View File

@ -91,14 +91,14 @@ public class TestCaseReviewController {
@PostMapping("/projects")
public List<Project> getProjectByReviewId(@RequestBody TestReviewRelevanceRequest request) {
List<String> projectIds = testReviewProjectService.getProjectIdsByPlanId(request.getReviewId());
List<String> projectIds = testReviewProjectService.getProjectIdsByReviewId(request.getReviewId());
request.setProjectIds(projectIds);
return testReviewProjectService.getProject(request);
}
@PostMapping("/project/{goPage}/{pageSize}")
public Pager<List<Project>> getProjectByReviewId(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody TestReviewRelevanceRequest request) {
List<String> projectIds = testReviewProjectService.getProjectIdsByPlanId(request.getReviewId());
List<String> projectIds = testReviewProjectService.getProjectIdsByReviewId(request.getReviewId());
request.setProjectIds(projectIds);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, testReviewProjectService.getProject(request));

View File

@ -0,0 +1,62 @@
package io.metersphere.track.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.base.domain.TestCaseReport;
import io.metersphere.base.domain.TestPlanReport;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.track.dto.TestCaseReportMetricDTO;
import io.metersphere.track.dto.TestPlanDTOWithMetric;
import io.metersphere.track.dto.TestPlanReportDTO;
import io.metersphere.track.request.report.QueryTestPlanReportRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.service.TestPlanReportService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* @author song.tianyang
* @Date 2021/1/8 2:38 下午
* @Description
*/
@RequestMapping("/test/plan/report")
@RestController
public class TestPlanReportController {
@Resource
private TestPlanReportService testPlanReportService;
@PostMapping("/list/{goPage}/{pageSize}")
public Pager<List<TestPlanReportDTO>> list(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanReportRequest request) {
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
request.setWorkspaceId(currentWorkspaceId);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, testPlanReportService.list(request));
}
@GetMapping("/getMetric/{planId}")
public TestPlanReportDTO getMetric(@PathVariable String planId) {
return testPlanReportService.getMetric(planId);
}
@GetMapping("/sendTask/{planId}")
public String sendTask(@PathVariable String planId) {
TestPlanReport report = testPlanReportService.getTestPlanReport(planId);
testPlanReportService.update(report);
return "sucess";
}
@PostMapping("/delete")
public void delete(@RequestBody List<String> testPlanReportIdList) {
testPlanReportService.delete(testPlanReportIdList);
}
@GetMapping("/apiExecuteFinish/{planId}/{userId}")
public void apiExecuteFinish(@PathVariable String planId,@PathVariable String userId) {
TestPlanReport report = testPlanReportService.genTestPlanReport(planId,userId,ReportTriggerMode.API.name());
testPlanReportService.countReportByTestPlanReportId(report.getId(),null, ReportTriggerMode.API.name());
}
}

View File

@ -12,4 +12,5 @@ public class TestPlanDTO extends TestPlan {
private String projectName;
private String userName;
private List<String> projectIds;
private String scheduleId;
}

View File

@ -0,0 +1,33 @@
package io.metersphere.track.dto;
import io.metersphere.base.domain.Issues;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
/**
* @author song.tianyang
* @Date 2021/1/8 2:39 下午
* @Description
*/
@Getter
@Setter
public class TestPlanReportDTO {
private String id;
private String name;
private String testPlanName;
private String creator;
private long createTime;
private String triggerMode;
private TestCaseReportAdvanceStatusResultDTO executeResult;
private List<TestCaseReportModuleResultDTO> moduleExecuteResult;
private FailureTestCasesAdvanceDTO failureTestCases;
private List<Issues> Issues;
private List<String> executors;
private String principal;
private Long startTime;
private Long endTime;
private String projectName;
}

View File

@ -0,0 +1,29 @@
package io.metersphere.track.request.report;
import io.metersphere.controller.request.OrderRequest;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
import java.util.Map;
/**
* @author song.tianyang
* @Date 2021/1/8 4:36 下午
* @Description
*/
@Getter
@Setter
@Data
public class QueryTestPlanReportRequest {
private String name;
private String testPlanName;
private String creator;
private String workspaceId;
private String projectId;
private List<OrderRequest> orders;
private Map<String, List<String>> filters;
// private Map<String, Object> combine;
}

View File

@ -37,4 +37,6 @@ public class QueryCaseReviewRequest extends TestCaseReviewTestCase {
private Map<String, Object> combine;
private String projectId;
private String projectName;
}

View File

@ -0,0 +1,42 @@
package io.metersphere.track.service;
import io.metersphere.base.domain.LoadTestReport;
import io.metersphere.base.mapper.ext.ExtTestPlanLoadCaseMapper;
import io.metersphere.commons.constants.PerformanceTestStatus;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.consumer.LoadTestFinishEvent;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class LoadReportStatusEvent implements LoadTestFinishEvent {
@Resource
private ExtTestPlanLoadCaseMapper extTestPlanLoadCaseMapper;
private void updateLoadCaseStatus(LoadTestReport loadTestReport) {
String reportId = loadTestReport.getId();
String status = loadTestReport.getStatus();
if (StringUtils.isNotBlank(reportId)) {
String result = "";
if (StringUtils.equals(PerformanceTestStatus.Error.name(), status)) {
result = "error";
}
if (StringUtils.equals(PerformanceTestStatus.Completed.name(), status)) {
result = "success";
}
extTestPlanLoadCaseMapper.updateCaseStatus(reportId, result);
}
}
@Override
public void execute(LoadTestReport loadTestReport) {
if (StringUtils.equals(ReportTriggerMode.CASE.name(), loadTestReport.getTriggerMode())) {
if (StringUtils.equalsAny(loadTestReport.getStatus(),
PerformanceTestStatus.Completed.name(), PerformanceTestStatus.Error.name())) {
updateLoadCaseStatus(loadTestReport);
}
}
}
}

View File

@ -1,66 +0,0 @@
package io.metersphere.track.service;
import io.metersphere.base.domain.LoadTestReportWithBLOBs;
import io.metersphere.base.domain.TestPlanLoadCase;
import io.metersphere.base.mapper.LoadTestReportMapper;
import io.metersphere.base.mapper.TestPlanLoadCaseMapper;
import io.metersphere.commons.constants.PerformanceTestStatus;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Component
public class LoadReportStatusTask {
@Resource
private LoadTestReportMapper loadTestReportMapper;
@Resource
private TestPlanLoadCaseMapper testPlanLoadCaseMapper;
private final ExecutorService executorService = Executors.newFixedThreadPool(20);
private boolean isRunning = false;
@PreDestroy
public void preDestroy() {
isRunning = false;
}
public void registerReportIsEndTask(String id, String reportId) {
isRunning = true;
// todo 手动创建线程池
executorService.submit(() -> {
while (isRunning) {
LoadTestReportWithBLOBs report = loadTestReportMapper.selectByPrimaryKey(reportId);
if (StringUtils.equalsAny(report.getStatus(), PerformanceTestStatus.Completed.name(), PerformanceTestStatus.Error.name())) {
updateLoadCaseStatus(id, report.getStatus());
return;
}
try {
//查询定时任务是否关闭
Thread.sleep(1000 * 10);// 检查 loadtest 的状态
} catch (InterruptedException e) {
LogUtil.error(e.getMessage(), e);
}
}
});
}
private void updateLoadCaseStatus(String testPlanLoadCaseId, String status) {
TestPlanLoadCase testPlanLoadCase = new TestPlanLoadCase();
testPlanLoadCase.setId(testPlanLoadCaseId);
String result = "";
if (StringUtils.equals(PerformanceTestStatus.Error.name(), status)) {
result = "error";
}
if (StringUtils.equals(PerformanceTestStatus.Completed.name(), status)) {
result = "success";
}
testPlanLoadCase.setStatus(result);
testPlanLoadCaseMapper.updateByPrimaryKeySelective(testPlanLoadCase);
}
}

View File

@ -83,12 +83,17 @@ public class TestCaseReviewService {
String reviewId = UUID.randomUUID().toString();
List<String> projectIds = reviewRequest.getProjectIds();
List<String> userIds = reviewRequest.getUserIds();//执行人
projectIds.forEach(projectId -> {
TestCaseReviewProject testCaseReviewProject = new TestCaseReviewProject();
testCaseReviewProject.setProjectId(projectId);
testCaseReviewProject.setReviewId(reviewId);
testCaseReviewProjectMapper.insertSelective(testCaseReviewProject);
});
if (!CollectionUtils.isEmpty(projectIds)) {
List<String> ids = projectIds.stream().distinct().collect(Collectors.toList());
// 如果关联项目id中包含当前项目id进行移除
ids.remove(SessionUtils.getCurrentProjectId());
ids.forEach(projectId -> {
TestCaseReviewProject testCaseReviewProject = new TestCaseReviewProject();
testCaseReviewProject.setProjectId(projectId);
testCaseReviewProject.setReviewId(reviewId);
testCaseReviewProjectMapper.insertSelective(testCaseReviewProject);
});
}
userIds.forEach(userId -> {
TestCaseReviewUsers testCaseReviewUsers = new TestCaseReviewUsers();
@ -102,6 +107,7 @@ public class TestCaseReviewService {
reviewRequest.setUpdateTime(System.currentTimeMillis());
reviewRequest.setCreator(SessionUtils.getUser().getId());//创建人
reviewRequest.setStatus(TestCaseReviewStatus.Prepare.name());
reviewRequest.setProjectId(SessionUtils.getCurrentProjectId());
testCaseReviewMapper.insert(reviewRequest);
// 发送通知
String context = getReviewContext(reviewRequest, NoticeConstants.Event.CREATE);
@ -156,7 +162,10 @@ public class TestCaseReviewService {
public List<TestCaseReviewDTO> listCaseReview(QueryCaseReviewRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
request.setProjectId(SessionUtils.getCurrentProjectId());
String projectId = request.getProjectId();
if (StringUtils.isBlank(projectId)) {
return new ArrayList<>();
}
return extTestCaseReviewMapper.list(request);
}
@ -172,6 +181,9 @@ public class TestCaseReviewService {
.map(TestCaseReviewProject::getProjectId)
.collect(Collectors.toList());
TestCaseReview testCaseReview = testCaseReviewMapper.selectByPrimaryKey(reviewId);
String projectId = testCaseReview.getProjectId();
projectIds.add(projectId);
ProjectExample projectExample = new ProjectExample();
projectExample.createCriteria().andIdIn(projectIds);
return projectMapper.selectByExample(projectExample);
@ -249,8 +261,11 @@ public class TestCaseReviewService {
private void editCaseReviewProject(SaveTestCaseReviewRequest testCaseReview) {
List<String> projectIds = testCaseReview.getProjectIds();
String id = testCaseReview.getId();
if (!CollectionUtils.isEmpty(projectIds)) {
projectIds.remove(testCaseReview.getProjectId());
}
String id = testCaseReview.getId();
if (StringUtils.isNotBlank(testCaseReview.getProjectId())) {
TestCaseReviewProjectExample testCaseReviewProjectExample = new TestCaseReviewProjectExample();
testCaseReviewProjectExample.createCriteria().andReviewIdEqualTo(id);
List<TestCaseReviewProject> testCaseReviewProjects = testCaseReviewProjectMapper.selectByExample(testCaseReviewProjectExample);
@ -265,15 +280,24 @@ public class TestCaseReviewService {
});
TestCaseReviewProjectExample example = new TestCaseReviewProjectExample();
example.createCriteria().andReviewIdEqualTo(id).andProjectIdNotIn(projectIds);
TestCaseReviewProjectExample.Criteria criteria1 = example.createCriteria().andReviewIdEqualTo(id);
if (!CollectionUtils.isEmpty(projectIds)) {
criteria1.andProjectIdNotIn(projectIds);
}
testCaseReviewProjectMapper.deleteByExample(example);
// 关联的项目下的用例idList
TestCaseExample testCaseExample = new TestCaseExample();
testCaseExample.createCriteria().andProjectIdIn(projectIds);
List<TestCase> caseList = testCaseMapper.selectByExample(testCaseExample);
List<String> caseIds = caseList.stream().map(TestCase::getId).collect(Collectors.toList());
List<String> caseIds = null;
// 测试计划所属项目下的用例不解除关联
projectIds.add(testCaseReview.getProjectId());
// 关联的项目下的用例idList
if (!CollectionUtils.isEmpty(projectIds)) {
TestCaseExample testCaseExample = new TestCaseExample();
testCaseExample.createCriteria().andProjectIdIn(projectIds);
List<TestCase> caseList = testCaseMapper.selectByExample(testCaseExample);
caseIds = caseList.stream().map(TestCase::getId).collect(Collectors.toList());
}
TestCaseReviewTestCaseExample testCaseReviewTestCaseExample = new TestCaseReviewTestCaseExample();
TestCaseReviewTestCaseExample.Criteria criteria = testCaseReviewTestCaseExample.createCriteria().andReviewIdEqualTo(id);
@ -282,6 +306,7 @@ public class TestCaseReviewService {
}
testCaseReviewTestCaseMapper.deleteByExample(testCaseReviewTestCaseExample);
}
}
private void checkCaseReviewExist(TestCaseReview testCaseReview) {
@ -348,19 +373,11 @@ public class TestCaseReviewService {
}
public List<TestCaseReview> listCaseReviewAll() {
TestCaseReviewProjectExample reviewProjectExample = new TestCaseReviewProjectExample();
TestCaseReviewProjectExample.Criteria criteria = reviewProjectExample.createCriteria();
if (StringUtils.isNotBlank(SessionUtils.getCurrentProjectId())) {
criteria.andProjectIdEqualTo(SessionUtils.getCurrentProjectId());
List<TestCaseReviewProject> testCaseReviewProjects = testCaseReviewProjectMapper.selectByExample(reviewProjectExample);
if (!CollectionUtils.isEmpty(testCaseReviewProjects)) {
List<String> caseReviewIds = testCaseReviewProjects.stream().map(TestCaseReviewProject::getReviewId).collect(Collectors.toList());
TestCaseReviewExample testCaseReviewExample = new TestCaseReviewExample();
testCaseReviewExample.createCriteria().andIdIn(caseReviewIds);
return testCaseReviewMapper.selectByExample(testCaseReviewExample);
}
TestCaseReviewExample testCaseReviewExample = new TestCaseReviewExample();
testCaseReviewExample.createCriteria().andProjectIdEqualTo(SessionUtils.getCurrentProjectId());
return testCaseReviewMapper.selectByExample(testCaseReviewExample);
}
return new ArrayList<>();
}

View File

@ -107,6 +107,10 @@ public class TestPlanApiCaseService {
return testPlanApiCaseMapper.selectByExample(example);
}
public TestPlanApiCase getById(String id) {
return testPlanApiCaseMapper.selectByPrimaryKey(id);
}
public void setExecResult(String id, String status) {
TestPlanApiCase apiCase = new TestPlanApiCase();
apiCase.setId(id);
@ -114,6 +118,10 @@ public class TestPlanApiCaseService {
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
}
public void updateByPrimaryKeySelective(TestPlanApiCase apiCase) {
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
}
public void deleteByRelevanceProjectIds(String planId, List<String> relevanceProjectIds) {
TestPlanApiCaseBatchRequest request = new TestPlanApiCaseBatchRequest();
request.setPlanId(planId);

View File

@ -0,0 +1,35 @@
package io.metersphere.track.service;
import io.metersphere.base.domain.LoadTestReport;
import io.metersphere.base.domain.TestPlanReport;
import io.metersphere.commons.constants.NoticeConstants;
import io.metersphere.commons.constants.PerformanceTestStatus;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.consumer.LoadTestFinishEvent;
import io.metersphere.commons.utils.LogUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* @author song.tianyang
* @Date 2021/1/13 2:53 下午
* @Description
*/
@Service
public class TestPlanLoadCaseEvent implements LoadTestFinishEvent {
@Resource
TestPlanReportService testPlanReportService;
@Override
public void execute(LoadTestReport loadTestReport) {
LogUtil.info("PerformanceNoticeEvent OVER:" + loadTestReport.getTriggerMode()+";"+loadTestReport.getStatus());
if (StringUtils.equals(NoticeConstants.Mode.SCHEDULE, loadTestReport.getTriggerMode()) ) {
if (StringUtils.equalsAny(loadTestReport.getStatus(),
PerformanceTestStatus.Completed.name(), PerformanceTestStatus.Error.name())) {
testPlanReportService.updatePerformanceTestStatus(loadTestReport.getId(), ReportTriggerMode.SCHEDULE.name());
}
}
}
}

View File

@ -40,8 +40,6 @@ public class TestPlanLoadCaseService {
private LoadTestReportMapper loadTestReportMapper;
@Resource
private LoadTestMapper loadTestMapper;
@Resource
private LoadReportStatusTask loadReportStatusTask;
public List<LoadTest> relevanceList(LoadCaseRequest request) {
List<String> ids = extTestPlanLoadCaseMapper.selectIdsNotInPlan(request.getProjectId(), request.getTestPlanId());
@ -85,7 +83,6 @@ public class TestPlanLoadCaseService {
testPlanLoadCase.setId(request.getTestPlanLoadId());
testPlanLoadCase.setLoadReportId(reportId);
testPlanLoadCaseMapper.updateByPrimaryKeySelective(testPlanLoadCase);
loadReportStatusTask.registerReportIsEndTask(request.getTestPlanLoadId(), reportId);
return reportId;
}

View File

@ -0,0 +1,397 @@
package io.metersphere.track.service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.jmeter.TestResult;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.*;
import io.metersphere.base.mapper.ext.ExtTestPlanApiCaseMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanReportMapper;
import io.metersphere.commons.constants.*;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.DateUtils;
import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.i18n.Translator;
import io.metersphere.notice.sender.NoticeModel;
import io.metersphere.notice.service.NoticeSendService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.track.Factory.ReportComponentFactory;
import io.metersphere.track.domain.ReportComponent;
import io.metersphere.track.dto.*;
import io.metersphere.track.request.report.QueryTestPlanReportRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.LoadCaseRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
/**
* @author song.tianyang
* @Date 2021/1/8 4:34 下午
* @Description
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanReportService {
@Resource
TestPlanReportMapper testPlanReportMapper;
@Resource
TestPlanReportDataMapper testPlanReportDataMapper;
@Resource
TestPlanApiScenarioMapper testPlanScenarioCaseMapper;
@Resource
TestPlanApiCaseMapper testPlanApiCaseMapper;
@Resource
ExtTestPlanReportMapper extTestPlanReportMapper;
@Resource
TestPlanMapper testPlanMapper;
@Resource
ExtTestPlanMapper extTestPlanMapper;
@Resource
ExtTestPlanApiCaseMapper extTestPlanApiCaseMapper;
@Resource
TestPlanLoadCaseService testPlanLoadCaseService;
@Resource
TestPlanService testPlanService;
@Resource
LoadTestReportMapper loadTestReportMapper;
private final ExecutorService executorService = Executors.newFixedThreadPool(20);
public List<TestPlanReportDTO> list(QueryTestPlanReportRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
String projectId = SessionUtils.getCurrentProjectId();
if (StringUtils.isNotBlank(projectId)) {
request.setProjectId(projectId);
}
List<TestPlanReportDTO> returnList = extTestPlanReportMapper.list(request);
return returnList;
}
public TestPlanReport genTestPlanReport(String planId, String userId,String triggerMode) {
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
TestPlanApiCaseExample apiExample = new TestPlanApiCaseExample();
apiExample.createCriteria().andTestPlanIdEqualTo(planId);
List<String> apiCaseIdList = testPlanApiCaseMapper.selectByExample(apiExample)
.stream().map(TestPlanApiCase::getApiCaseId).collect(Collectors.toList());
TestPlanApiScenarioExample example = new TestPlanApiScenarioExample();
example.createCriteria().andTestPlanIdEqualTo(planId);
List<String> scenarioIdList = testPlanScenarioCaseMapper.selectByExample(example)
.stream().map(TestPlanApiScenario::getApiScenarioId).collect(Collectors.toList());
LoadCaseRequest loadCaseRequest = new LoadCaseRequest();
loadCaseRequest.setTestPlanId(planId);
loadCaseRequest.setProjectId(testPlan.getProjectId());
List<String> performanceIdList = testPlanLoadCaseService.list(loadCaseRequest)
.stream().map(TestPlanLoadCaseDTO::getLoadCaseId).collect(Collectors.toList());
String testPlanReportID = UUID.randomUUID().toString();
TestPlanReport testPlanReport = new TestPlanReport();
testPlanReport.setTestPlanId(planId);
testPlanReport.setId(testPlanReportID);
testPlanReport.setCreateTime(System.currentTimeMillis());
testPlanReport.setUpdateTime(System.currentTimeMillis());
try {
testPlanReport.setName(testPlan.getName() + "-" + DateUtils.getTimeString(new Date()));
} catch (Exception e) {
}
testPlanReport.setTriggerMode(triggerMode);
testPlanReport.setCreator(userId);
testPlanReport.setStartTime(System.currentTimeMillis());
testPlanReport.setEndTime(System.currentTimeMillis());
if (apiCaseIdList.isEmpty()) {
testPlanReport.setIsApiCaseExecuting(false);
} else {
testPlanReport.setIsApiCaseExecuting(true);
}
if (scenarioIdList.isEmpty()) {
testPlanReport.setIsScenarioExecuting(false);
} else {
testPlanReport.setIsScenarioExecuting(true);
}
if (performanceIdList.isEmpty()) {
testPlanReport.setIsPerformanceExecuting(false);
} else {
testPlanReport.setIsPerformanceExecuting(true);
}
testPlanReport.setPrincipal(testPlan.getPrincipal());
testPlanReportMapper.insert(testPlanReport);
TestPlanReportDataWithBLOBs testPlanReportData = new TestPlanReportDataWithBLOBs();
testPlanReportData.setId(UUID.randomUUID().toString());
testPlanReportData.setTestPlanReportId(testPlanReportID);
testPlanReportData.setApiCaseInfo(JSONArray.toJSONString(apiCaseIdList));
testPlanReportData.setScenarioInfo(JSONArray.toJSONString(scenarioIdList));
testPlanReportData.setPerformanceInfo(JSONArray.toJSONString(performanceIdList));
testPlanReportDataMapper.insert(testPlanReportData);
//更新TestPlan状态改为进行中
testPlan.setStatus(TestPlanStatus.Underway.name());
testPlanMapper.updateByPrimaryKeySelective(testPlan);
return testPlanReport;
}
public TestPlanReportDTO getMetric(String reportId) {
TestPlanReportDTO returnDTO = new TestPlanReportDTO();
TestPlanReport report = testPlanReportMapper.selectByPrimaryKey(reportId);
if (report != null) {
TestPlanReportDataExample example = new TestPlanReportDataExample();
example.createCriteria().andTestPlanReportIdEqualTo(reportId);
List<TestPlanReportDataWithBLOBs> reportDataList = testPlanReportDataMapper.selectByExampleWithBLOBs(example);
if (!reportDataList.isEmpty()) {
TestPlanReportDataWithBLOBs reportData = reportDataList.get(0);
if (!StringUtils.isEmpty(reportData.getExecuteResult())) {
returnDTO.setExecuteResult(JSONObject.parseObject(reportData.getExecuteResult(), TestCaseReportAdvanceStatusResultDTO.class));
}
if (!StringUtils.isEmpty(reportData.getModuleExecuteResult())) {
returnDTO.setModuleExecuteResult(JSONArray.parseArray(reportData.getModuleExecuteResult(), TestCaseReportModuleResultDTO.class));
}
if (!StringUtils.isEmpty(reportData.getFailurTestCases())) {
returnDTO.setFailureTestCases(JSONObject.parseObject(reportData.getFailurTestCases(), FailureTestCasesAdvanceDTO.class));
}
if (!StringUtils.isEmpty(reportData.getIssuesInfo())) {
returnDTO.setIssues(JSONArray.parseArray(reportData.getIssuesInfo(), Issues.class));
}
List<String> creatorList = new ArrayList<>();
creatorList.add(report.getCreator());
returnDTO.setExecutors(creatorList);
returnDTO.setPrincipal(report.getPrincipal());
returnDTO.setStartTime(report.getStartTime());
returnDTO.setEndTime(report.getEndTime());
String testProject = testPlanService.findTestProjectNameByTestPlanID(report.getTestPlanId());
returnDTO.setProjectName(testProject);
}
}
return returnDTO;
}
public synchronized void updateReport(List<String> testPlanReportIdList, String runMode,String triggerMode) {
for (String planReportId : testPlanReportIdList) {
this.countReportByTestPlanReportId(planReportId,runMode,triggerMode);
}
}
/**
*
* @param planReportId 测试计划报告ID
* @param resourceRunMode 资源的运行模式,triggerMode非Scedule可以为null
* @param triggerMode 触发方式 ReportTriggerMode.enum
*/
public void countReportByTestPlanReportId(String planReportId,String resourceRunMode,String triggerMode) {
TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(planReportId);
QueryTestPlanRequest queryTestPlanRequest = new QueryTestPlanRequest();
queryTestPlanRequest.setId(testPlanReport.getTestPlanId());
TestPlanDTO testPlan = extTestPlanMapper.list(queryTestPlanRequest).get(0);
//因为接口案例的定时任务是单个案例开线程运行 所以要检查是否都执行完成全部执行完成时才会进行统一整理
if (StringUtils.equals(ReportTriggerMode.SCHEDULE.name(),triggerMode)
&&StringUtils.equalsAny(resourceRunMode, ApiRunMode.SCHEDULE_API_PLAN.name())) {
List<String> statusList = extTestPlanApiCaseMapper.getStatusByTestPlanId(testPlan.getId());
for (String status : statusList) {
if (status == null) {
return;
}
}
}
testPlanReport.setEndTime(System.currentTimeMillis());
testPlanReport.setUpdateTime(System.currentTimeMillis());
JSONObject content = JSONObject.parseObject("{\"components\":[1,2,3,4,5]}");
JSONArray componentIds = content.getJSONArray("components");
List<ReportComponent> components = ReportComponentFactory.createComponents(componentIds.toJavaList(String.class), testPlan);
testPlanService.buildApiCaseReport(testPlanReport.getTestPlanId(), components);
testPlanService.buildScenarioCaseReport(testPlanReport.getTestPlanId(), components);
testPlanService.buildLoadCaseReport(testPlanReport.getTestPlanId(), components);
//只针对定时任务做处理
if (StringUtils.equals(ReportTriggerMode.SCHEDULE.name(),triggerMode)
&&StringUtils.equals(resourceRunMode, ApiRunMode.SCHEDULE_API_PLAN.name())) {
testPlanReport.setIsApiCaseExecuting(false);
} else if (StringUtils.equals(ReportTriggerMode.SCHEDULE.name(),triggerMode)
&&StringUtils.equals(resourceRunMode, ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) {
testPlanReport.setIsScenarioExecuting(false);
} else if (StringUtils.equals(ReportTriggerMode.SCHEDULE.name(),triggerMode)
&&StringUtils.equals(resourceRunMode, ApiRunMode.SCHEDULE_PERFORMANCE_TEST.name())) {
testPlanReport.setIsPerformanceExecuting(false);
}else {
testPlanReport.setIsPerformanceExecuting(false);
testPlanReport.setIsScenarioExecuting(false);
testPlanReport.setIsApiCaseExecuting(false);
}
TestCaseReportMetricDTO testCaseReportMetricDTO = new TestCaseReportMetricDTO();
components.forEach(component -> {
component.afterBuild(testCaseReportMetricDTO);
});
this.update(testPlanReport);
TestPlanReportDataExample example = new TestPlanReportDataExample();
example.createCriteria().andTestPlanReportIdEqualTo(planReportId);
List<TestPlanReportDataWithBLOBs> testPlanReportDataList = testPlanReportDataMapper.selectByExampleWithBLOBs(example);
if (!testPlanReportDataList.isEmpty()) {
TestPlanReportDataWithBLOBs testPlanReportData = testPlanReportDataList.get(0);
testPlanReportData.setExecuteResult(JSONObject.toJSONString(testCaseReportMetricDTO.getExecuteResult()));
testPlanReportData.setFailurTestCases(JSONObject.toJSONString(testCaseReportMetricDTO.getFailureTestCases()));
testPlanReportData.setModuleExecuteResult(JSONArray.toJSONString(testCaseReportMetricDTO.getModuleExecuteResult()));
testPlanReportDataMapper.updateByPrimaryKeyWithBLOBs(testPlanReportData);
}
}
public void update(TestPlanReport report) {
if (!report.getIsApiCaseExecuting() && !report.getIsPerformanceExecuting() && !report.getIsScenarioExecuting()) {
try {
//更新TestPlan状态为完成
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(report.getTestPlanId());
if (testPlan != null) {
testPlan.setStatus(TestPlanStatus.Completed.name());
testPlanMapper.updateByPrimaryKeySelective(testPlan);
}
//发送通知
sendMessage(report);
} catch (Exception e) {
}
}
testPlanReportMapper.updateByPrimaryKey(report);
}
public void sendMessage(TestPlanReport testPlanReport) {
TestPlan testPlan = testPlanService.getTestPlan(testPlanReport.getTestPlanId());
assert testPlan != null;
SystemParameterService systemParameterService = CommonBeanFactory.getBean(SystemParameterService.class);
NoticeSendService noticeSendService = CommonBeanFactory.getBean(NoticeSendService.class);
assert systemParameterService != null;
assert noticeSendService != null;
BaseSystemConfigDTO baseSystemConfigDTO = systemParameterService.getBaseInfo();
String url = baseSystemConfigDTO.getUrl() + "/#/track/testPlan/reportList";
String successContext = "";
String failedContext = "";
String subject = "";
String event = "";
successContext = "接口测试定时任务通知:'" + testPlan.getName() + "'执行成功" + "\n" + "请点击下面链接进入测试报告页面" + "\n" + url;
failedContext = "接口测试定时任务通知:'" + testPlan.getName() + "'执行失败" + "\n" + "请点击下面链接进入测试报告页面" + "\n" + url;
subject = Translator.get("task_notification");
if (StringUtils.equals("Success", testPlanReport.getStatus())) {
event = NoticeConstants.Event.EXECUTE_SUCCESSFUL;
} else {
event = NoticeConstants.Event.EXECUTE_FAILED;
}
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("testName", testPlan.getName());
paramMap.put("id", testPlanReport.getId());
paramMap.put("type", "api");
paramMap.put("url", url);
paramMap.put("status", testPlanReport.getStatus());
NoticeModel noticeModel = NoticeModel.builder()
.successContext(successContext)
.successMailTemplate("ApiSuccessfulNotification")
.failedContext(failedContext)
.failedMailTemplate("ApiFailedNotification")
.testId(testPlan.getId())
.status(testPlanReport.getStatus())
.event(event)
.subject(subject)
.paramMap(paramMap)
.build();
noticeSendService.send(testPlanReport.getTriggerMode(), noticeModel);
}
public TestPlanReport getTestPlanReport(String planId) {
return testPlanReportMapper.selectByPrimaryKey(planId);
}
/**
* 更新TestPlanReportData的PerformanceInfo
*
* @param testPlanReport
* @param performaneReportIDList
*/
public void updatePerformanceInfo(TestPlanReport testPlanReport, List<String> performaneReportIDList,String triggerMode) {
TestPlanReportDataExample example = new TestPlanReportDataExample();
example.createCriteria().andTestPlanReportIdEqualTo(testPlanReport.getId());
List<TestPlanReportDataWithBLOBs> reportDataList = testPlanReportDataMapper.selectByExampleWithBLOBs(example);
for (TestPlanReportDataWithBLOBs models : reportDataList) {
models.setPerformanceInfo(JSONArray.toJSONString(performaneReportIDList));
testPlanReportDataMapper.updateByPrimaryKeyWithBLOBs(models);
}
/**
* 虽然kafka已经设置了topic推送但是在1.18日测试时发现无法收到消息
* 由于Tapd为完成任务较多无法抽时间查看问题暂时先保留以下逻辑解决完Tpad任务之后查看原因再删除以下代码
*/
executorService.submit(() -> {
//错误数据检查集合 如果错误数据出现超过20次则取消该条数据的检查
Map<String,Integer> errorDataCheckMap = new HashMap<>();
while (performaneReportIDList.size()>0) {
List<String> selectList = new ArrayList<>(performaneReportIDList);
for (String loadTestReportId:selectList) {
LoadTestReportWithBLOBs loadTestReportFromDatabase = loadTestReportMapper.selectByPrimaryKey(loadTestReportId);
if(loadTestReportFromDatabase == null){
//检查错误数据
if(errorDataCheckMap.containsKey(loadTestReportId)){
if(errorDataCheckMap.get(loadTestReportId)>20){
performaneReportIDList.remove(loadTestReportId);
}else {
errorDataCheckMap.put(loadTestReportId,errorDataCheckMap.get(loadTestReportId)+1);
}
}else {
errorDataCheckMap.put(loadTestReportId,1);
}
}else if (StringUtils.equalsAny(loadTestReportFromDatabase.getStatus(),
PerformanceTestStatus.Completed.name(), PerformanceTestStatus.Error.name())) {
performaneReportIDList.remove(loadTestReportId);
System.out.println("over");
}
}
if(performaneReportIDList.isEmpty()){
List<String> testPlanReportList = new ArrayList<>();
testPlanReportList.add(testPlanReport.getId());
this.updateReport(testPlanReportList, ApiRunMode.SCHEDULE_PERFORMANCE_TEST.name(),triggerMode);
}else {
try {
//查询定时任务是否关闭
Thread.sleep(1000 * 10);// 检查 loadtest 的状态
} catch (InterruptedException e) {
}
}
}
return true;
});
}
public void updatePerformanceTestStatus(String reportId,String triggerMode) {
List<String> testPlanReportId = extTestPlanMapper.findIdByPerformanceReportId(reportId);
this.updateReport(testPlanReportId, ApiRunMode.SCHEDULE_PERFORMANCE_TEST.name(),triggerMode);
}
public void delete(List<String> testPlanReportIdList) {
for (String testPlanReportId : testPlanReportIdList) {
testPlanReportMapper.deleteByPrimaryKey(testPlanReportId);
TestPlanReportDataExample example = new TestPlanReportDataExample();
example.createCriteria().andTestPlanReportIdEqualTo(testPlanReportId);
testPlanReportDataMapper.deleteByExample(example);
}
}
}

View File

@ -720,4 +720,12 @@ public class TestPlanService {
public List<TestPlanDTO> selectTestPlanByRelevancy(QueryTestPlanRequest params){
return extTestPlanMapper.selectTestPlanByRelevancy(params);
}
public String findTestProjectNameByTestPlanID(String testPlanId) {
return extTestPlanMapper.findTestProjectNameByTestPlanID(testPlanId);
}
public String findScheduleCreateUserById(String testPlanId) {
return extTestPlanMapper.findScheduleCreateUserById(testPlanId);
}
}

View File

@ -2,6 +2,7 @@ package io.metersphere.track.service;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ProjectMapper;
import io.metersphere.base.mapper.TestCaseReviewMapper;
import io.metersphere.base.mapper.TestCaseReviewProjectMapper;
import io.metersphere.track.request.testreview.TestReviewRelevanceRequest;
import org.apache.commons.lang3.StringUtils;
@ -17,18 +18,25 @@ import java.util.stream.Collectors;
public class TestReviewProjectService {
@Resource
ProjectMapper projectMapper;
private ProjectMapper projectMapper;
@Resource
TestCaseReviewProjectMapper testCaseReviewProjectMapper;
private TestCaseReviewProjectMapper testCaseReviewProjectMapper;
@Resource
private TestCaseReviewMapper testCaseReviewMapper;
public List<String> getProjectIdsByPlanId(String reviewId) {
public List<String> getProjectIdsByReviewId(String reviewId) {
TestCaseReviewProjectExample example = new TestCaseReviewProjectExample();
example.createCriteria().andReviewIdEqualTo(reviewId);
List<String> projectIds = testCaseReviewProjectMapper.selectByExample(example)
.stream()
.map(TestCaseReviewProject::getProjectId)
.collect(Collectors.toList());
TestCaseReview caseReview = testCaseReviewMapper.selectByPrimaryKey(reviewId);
if (caseReview != null && StringUtils.isNotBlank(caseReview.getProjectId())) {
if (!projectIds.contains(caseReview.getProjectId())) {
projectIds.add(caseReview.getProjectId());
}
}
if (projectIds.isEmpty()) {
return null;
}

@ -1 +1 @@
Subproject commit 8d5b1ebeabf5ebaee9ca186087ac8a34cf888518
Subproject commit 36116c1bff736377e6b8a3b828c5fa9bd8b2f2f8

View File

@ -38,6 +38,7 @@ spring.flyway.table=metersphere_version
spring.flyway.baseline-version=0
spring.flyway.encoding=UTF-8
spring.flyway.validate-on-migrate=false
spring.kafka.listener.missing-topics-fatal=false
spring.messages.basename=i18n/messages

View File

@ -0,0 +1,36 @@
CREATE TABLE IF NOT EXISTS `test_plan_report` (
`id` VARCHAR ( 50 ) NOT NULL COMMENT 'ID',
`test_plan_id` VARCHAR ( 50 ) NOT NULL COMMENT 'Test plan ID',
`create_time` BIGINT ( 13 ) NOT NULL COMMENT 'Create timestamp',
`update_time` BIGINT ( 13 ) NOT NULL COMMENT 'Update timestamp',
`name` VARCHAR ( 64 ) DEFAULT NULL COMMENT 'name',
`status` VARCHAR ( 50 ) DEFAULT NULL COMMENT 'report status',
`trigger_mode` VARCHAR ( 50 ) DEFAULT NULL COMMENT 'test plan execute triggerMode',
`creator` VARCHAR ( 50 ) DEFAULT NULL COMMENT 'report creator',
`start_time` BIGINT ( 13 ) DEFAULT NULL COMMENT 'report startTime',
`end_time` BIGINT ( 13 ) DEFAULT NULL COMMENT 'report timestamp',
`is_api_case_executing` TINYINT NOT NULL COMMENT 'is Api Case executing',
`is_scenario_executing` TINYINT NOT NULL COMMENT 'is scenario Case executing',
`is_performance_executing` TINYINT NOT NULL COMMENT 'is performance executing',
`principal` VARCHAR ( 50 ) DEFAULT NULL COMMENT 'principal',
PRIMARY KEY ( `id` ),
UNIQUE KEY `executeInfoID` ( `test_plan_id`, `create_time` )
)
ENGINE = INNODB
DEFAULT CHARSET = utf8mb4;
CREATE TABLE IF NOT EXISTS `test_plan_report_data` (
`id` VARCHAR ( 50 ) NOT NULL COMMENT 'ID',
`test_plan_report_id` VARCHAR ( 50 ) NOT NULL COMMENT 'Test plan ID',
`execute_result` longtext COMMENT 'executeResult (JSON format)',
`failur_test_cases` longtext COMMENT 'failurTestCases (JSON format)',
`module_execute_result` longtext COMMENT 'moduleExecuteResult (JSON format)',
`api_case_info` longtext COMMENT 'apiCaseID list (JSON format)',
`scenario_info` longtext COMMENT 'scenarioID list (JSON format)',
`performance_info` longtext COMMENT 'performanceID list (JSON format)',
`issues_info` longtext COMMENT 'issues (JSON format)',
PRIMARY KEY ( `id` ),
UNIQUE KEY `test_plan_report_id` ( `test_plan_report_id` )
)
ENGINE = INNODB
DEFAULT CHARSET = utf8mb4;

View File

@ -0,0 +1,55 @@
alter table test_case_review add project_id varchar(50) null comment '用例评审所属项目';
DROP PROCEDURE IF EXISTS test_cursor;
DELIMITER //
CREATE PROCEDURE test_cursor()
BEGIN
DECLARE reviewId VARCHAR(64);
DECLARE done INT DEFAULT 0;
DECLARE cursor1 CURSOR FOR (SELECT id
FROM test_case_review
WHERE project_id IS NULL);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor1;
outer_loop:
LOOP
FETCH cursor1 INTO reviewId;
IF done
THEN
LEAVE outer_loop;
END IF;
select count(1) as s, project_id
into @num, @projectId
from test_case_review_test_case
join test_case on case_id = test_case.id
where review_id = reviewId
group by project_id
order by s desc
limit 1;
IF @projectId = ''
THEN
select test_case_review_project.project_id
into @projectId
from test_case_review
join test_case_review_project on test_case_review.id = test_case_review_project.review_id
where test_case_review.id = reviewId
limit 1;
END IF;
UPDATE test_case_review SET test_case_review.project_id = @projectId WHERE test_case_review.id = reviewId;
DELETE FROM test_case_review_project
WHERE test_case_review_project.project_id = @projectId
AND test_case_review_project.review_id = reviewId;
SET @projectId = '';
SET done = 0;
END LOOP;
CLOSE cursor1;
END //
DELIMITER ;
CALL test_cursor();
DROP PROCEDURE IF EXISTS test_cursor;

View File

@ -15,7 +15,7 @@
"@fortawesome/free-regular-svg-icons": "^5.12.0",
"@fortawesome/free-solid-svg-icons": "^5.12.0",
"@fortawesome/vue-fontawesome": "^0.1.9",
"axios": "^0.19.0",
"axios": "^0.21.1",
"core-js": "^3.4.3",
"diffable-html": "^4.0.0",
"echarts": "^4.6.0",
@ -39,14 +39,14 @@
"vue-float-action-button": "^0.6.6",
"vue-i18n": "^8.15.3",
"vue-input-tag": "^2.0.7",
"vue-jsonpath-picker": "^1.1.5",
"vue-papa-parse": "^2.0.0",
"vue-pdf": "^4.2.0",
"vue-router": "^3.1.3",
"vuedraggable": "^2.23.2",
"vuex": "^3.1.2",
"xml-js": "^1.6.11",
"yan-progress": "^1.0.3",
"vue-jsonpath-picker": "^1.1.5"
"yan-progress": "^1.0.3"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.1.0",

View File

@ -38,7 +38,14 @@
<el-tab-pane name="add">
<template v-slot:label>
<el-button type="primary" plain icon="el-icon-plus" size="mini" v-tester/>
<el-dropdown @command="handleCommand" v-tester>
<el-button type="primary" plain icon="el-icon-plus" size="mini" v-tester/>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="ADD">{{ $t('api_test.definition.request.title') }}</el-dropdown-item>
<el-dropdown-item command="CLOSE_ALL">{{ $t('api_test.definition.request.close_all_label') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-tab-pane>
</el-tabs>
@ -48,150 +55,168 @@
<script>
import MsContainer from "@/business/components/common/components/MsContainer";
import MsAsideContainer from "@/business/components/common/components/MsAsideContainer";
import MsMainContainer from "@/business/components/common/components/MsMainContainer";
import MsApiScenarioList from "@/business/components/api/automation/scenario/ApiScenarioList";
import {getUUID} from "@/common/js/utils";
import MsApiScenarioModule from "@/business/components/api/automation/scenario/ApiScenarioModule";
import MsEditApiScenario from "./scenario/EditApiScenario";
import {getCurrentProjectID} from "../../../../common/js/utils";
import MsContainer from "@/business/components/common/components/MsContainer";
import MsAsideContainer from "@/business/components/common/components/MsAsideContainer";
import MsMainContainer from "@/business/components/common/components/MsMainContainer";
import MsApiScenarioList from "@/business/components/api/automation/scenario/ApiScenarioList";
import {getUUID} from "@/common/js/utils";
import MsApiScenarioModule from "@/business/components/api/automation/scenario/ApiScenarioModule";
import MsEditApiScenario from "./scenario/EditApiScenario";
import {getCurrentProjectID} from "../../../../common/js/utils";
export default {
name: "ApiAutomation",
components: {
MsApiScenarioModule,
MsApiScenarioList,
MsMainContainer,
MsAsideContainer,
MsContainer,
MsEditApiScenario
},
comments: {},
computed: {
checkRedirectID: function () {
let redirectIDParam = this.$route.params.redirectID;
this.changeRedirectParam(redirectIDParam);
return redirectIDParam;
export default {
name: "ApiAutomation",
components: {
MsApiScenarioModule,
MsApiScenarioList,
MsMainContainer,
MsAsideContainer,
MsContainer,
MsEditApiScenario
},
isRedirectEdit: function () {
let redirectParam = this.$route.params.dataSelectRange;
this.checkRedirectEditPage(redirectParam);
return redirectParam;
}
},
data() {
return {
redirectID: '',
renderComponent: true,
isHide: true,
activeName: 'default',
currentModule: null,
moduleOptions: [],
tabs: [],
trashEnable: false,
selectNodeIds: [],
}
},
watch: {
redirectID() {
this.renderComponent = false;
this.$nextTick(() => {
// DOM my-component
this.renderComponent = true;
});
}
},
methods: {
checkRedirectEditPage(redirectParam) {
if(redirectParam!=null){
let selectParamArr = redirectParam.split("edit:");
if (selectParamArr.length == 2) {
let scenarioId = selectParamArr[1];
let projectId = getCurrentProjectID();
//
let url = "/api/automation/list/" + 1 + "/" + 1;
this.$post(url, {id:scenarioId,projectId:projectId}, response => {
let data = response.data;
if(data!=null){
//
if(JSON.stringify(this.moduleOptions) === '{}' ){
this.$refs.nodeTree.list();
comments: {},
computed: {
checkRedirectID: function () {
let redirectIDParam = this.$route.params.redirectID;
this.changeRedirectParam(redirectIDParam);
return redirectIDParam;
},
isRedirectEdit: function () {
let redirectParam = this.$route.params.dataSelectRange;
this.checkRedirectEditPage(redirectParam);
return redirectParam;
}
},
data() {
return {
redirectID: '',
renderComponent: true,
isHide: true,
activeName: 'default',
currentModule: null,
moduleOptions: [],
tabs: [],
trashEnable: false,
selectNodeIds: [],
}
},
watch: {
redirectID() {
this.renderComponent = false;
this.$nextTick(() => {
// DOM my-component
this.renderComponent = true;
});
}
},
methods: {
checkRedirectEditPage(redirectParam) {
if (redirectParam != null) {
let selectParamArr = redirectParam.split("edit:");
if (selectParamArr.length == 2) {
let scenarioId = selectParamArr[1];
let projectId = getCurrentProjectID();
//
let url = "/api/automation/list/" + 1 + "/" + 1;
this.$post(url, {id: scenarioId, projectId: projectId}, response => {
let data = response.data;
if (data != null) {
//
if (JSON.stringify(this.moduleOptions) === '{}') {
this.$refs.nodeTree.list();
}
let row = data.listObject[0];
row.tags = JSON.parse(row.tags);
this.editScenario(row);
}
let row = data.listObject[0];
row.tags = JSON.parse(row.tags);
this.editScenario(row);
}
});
});
}
}
}
},
changeRedirectParam(redirectIDParam) {
this.redirectID = redirectIDParam;
},
addTab(tab) {
if (!getCurrentProjectID()) {
this.$warning(this.$t('commons.check_project_tip'));
return;
}
if (tab.name === 'add') {
let label = this.$t('api_test.automation.add_scenario');
let name = getUUID().substring(0, 8);
this.activeName = name;
this.tabs.push({label: label, name: name, currentScenario: {apiScenarioModuleId: "", id: getUUID()}});
}
if (tab.name === 'edit') {
let label = this.$t('api_test.automation.add_scenario');
let name = getUUID().substring(0, 8);
this.activeName = name;
label = tab.currentScenario.name;
this.tabs.push({label: label, name: name, currentScenario: tab.currentScenario});
}
},
removeTab(targetName) {
this.tabs = this.tabs.filter(tab => tab.name !== targetName);
if (this.tabs.length > 0) {
this.activeName = this.tabs[this.tabs.length - 1].name;
} else {
this.activeName = "default"
}
},
setTabLabel(data) {
for (const tab of this.tabs) {
if (tab.name === this.activeName) {
tab.label = data.name;
break;
},
changeRedirectParam(redirectIDParam) {
this.redirectID = redirectIDParam;
},
addTab(tab) {
if (!getCurrentProjectID()) {
this.$warning(this.$t('commons.check_project_tip'));
return;
}
}
},
selectModule(data) {
this.currentModule = data;
},
saveScenario(data) {
this.setTabLabel(data);
this.$refs.apiScenarioList.search(data);
},
refresh(data) {
this.$refs.apiScenarioList.search(data);
},
editScenario(row) {
this.addTab({name: 'edit', currentScenario: row});
},
if (tab.name === 'add') {
let label = this.$t('api_test.automation.add_scenario');
let name = getUUID().substring(0, 8);
this.activeName = name;
this.tabs.push({label: label, name: name, currentScenario: {apiScenarioModuleId: "", id: getUUID()}});
}
if (tab.name === 'edit') {
let label = this.$t('api_test.automation.add_scenario');
let name = getUUID().substring(0, 8);
this.activeName = name;
label = tab.currentScenario.name;
this.tabs.push({label: label, name: name, currentScenario: tab.currentScenario});
}
},
handleTabClose() {
this.tabs = [];
this.activeName = "default";
this.refresh();
},
handleCommand(e) {
switch (e) {
case "ADD":
this.addTab({name: 'add'});
break;
case "CLOSE_ALL":
this.handleTabClose();
break;
default:
this.addTab({name: 'add'});
break;
}
},
removeTab(targetName) {
this.tabs = this.tabs.filter(tab => tab.name !== targetName);
if (this.tabs.length > 0) {
this.activeName = this.tabs[this.tabs.length - 1].name;
} else {
this.activeName = "default"
}
},
setTabLabel(data) {
for (const tab of this.tabs) {
if (tab.name === this.activeName) {
tab.label = data.name;
break;
}
}
},
selectModule(data) {
this.currentModule = data;
},
saveScenario(data) {
this.setTabLabel(data);
this.$refs.apiScenarioList.search(data);
},
refresh(data) {
this.$refs.apiScenarioList.search(data);
},
editScenario(row) {
this.addTab({name: 'edit', currentScenario: row});
},
nodeChange(node, nodeIds, pNodes) {
this.selectNodeIds = nodeIds;
},
setModuleOptions(data) {
this.moduleOptions = data;
},
changeSelectDataRangeAll(tableType) {
this.$route.params.dataSelectRange = 'all';
},
enableTrash(data) {
this.trashEnable = data;
nodeChange(node, nodeIds, pNodes) {
this.selectNodeIds = nodeIds;
},
setModuleOptions(data) {
this.moduleOptions = data;
},
changeSelectDataRangeAll(tableType) {
this.$route.params.dataSelectRange = 'all';
},
enableTrash(data) {
this.trashEnable = data;
}
}
}
}
</script>
<style scoped>

View File

@ -12,7 +12,7 @@
<el-table-column type="selection" width="50"/>
<ms-table-select-all v-if="!referenced"
:page-size="pageSize"
:page-size="pageSize>total?total:pageSize"
:total="total"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>

View File

@ -145,31 +145,12 @@
@node-expand="nodeExpand"
@node-collapse="nodeCollapse"
:allow-drop="allowDrop" @node-drag-end="allowDrag" @node-click="nodeClick" v-if="!loading" draggable>
<span class="custom-tree-node father" slot-scope="{ node, data}" style="width: 96%">
<template>
<!-- 场景 -->
<ms-api-scenario-component v-if="data.type==='scenario'" :scenario="data" :node="node" @remove="remove" @copyRow="copyRow"/>
<!--条件控制器-->
<ms-if-controller :controller="data" :node="node" v-if="data.type==='IfController'" @remove="remove" @copyRow="copyRow"/>
<!--循环控制器-->
<ms-loop-controller :controller="data" :node="node" v-if="data.type==='LoopController'" @remove="remove" @copyRow="copyRow"/>
<!--等待控制器-->
<ms-constant-timer :timer="data" :node="node" v-if="data.type==='ConstantTimer'" @remove="remove" @copyRow="copyRow"/>
<!--自定义脚本-->
<ms-jsr233-processor :draggable="true" v-if="data.type==='JSR223Processor'" @remove="remove" @copyRow="copyRow" :title="$t('api_test.automation.customize_script')" :jsr223-processor="data" :node="node"/>
<!--前置脚本-->
<ms-jsr233-processor :draggable="true" v-if="data.type==='JSR223PreProcessor'" @remove="remove" @copyRow="copyRow" :title="$t('api_test.definition.request.pre_script')" :jsr223-processor="data" :node="node"/>
<!--后置脚本-->
<ms-jsr233-processor :draggable="true" v-if="data.type==='JSR223PostProcessor'" @remove="remove" @copyRow="copyRow" :title="$t('api_test.definition.request.post_script')" :jsr223-processor="data" :node="node"/>
<!--断言规则-->
<ms-api-assertions :draggable="true" @suggestClick="suggestClick(node)" :response="response" v-if="data.type==='Assertions'" @remove="remove" @copyRow="copyRow" :assertions="data" :node="node"/>
<!--提取规则-->
<ms-api-extract :draggable="true" @suggestClick="suggestClick(node)" :response="response" @remove="remove" @copyRow="copyRow" v-if="data.type==='Extract'" :extract="data" :node="node"/>
<!--API 导入 -->
<ms-api-component :request="data" :currentScenario="currentScenario" :currentEnvironmentId="currentEnvironmentId" @remove="remove" @copyRow="copyRow"
v-if="data.type==='HTTPSamplerProxy'||data.type==='DubboSampler'||data.type==='JDBCSampler'||data.type==='TCPSampler'" :node="node"/>
</template>
</span>
<span class="custom-tree-node father" slot-scope="{ node, data}" style="width: 96%">
<!-- 步骤组件-->
<ms-component-config :type="data.type" :scenario="data" :response="response" :currentScenario="currentScenario"
:currentEnvironmentId="currentEnvironmentId" :node="node"
@remove="remove" @copyRow="copyRow" @suggestClick="suggestClick"/>
</span>
</el-tree>
</div>
</el-col>
@ -227,21 +208,13 @@
import {API_STATUS, PRIORITY} from "../../definition/model/JsonData";
import {WORKSPACE_ID} from '@/common/js/constants';
import {Assertions, Extract, IfController, JSR223Processor, ConstantTimer, LoopController} from "../../definition/model/ApiTestModel";
import MsJsr233Processor from "./Jsr233Processor";
import {parseEnvironment} from "../../definition/model/EnvironmentModel";
import MsConstantTimer from "./ConstantTimer";
import MsIfController from "./IfController";
import MsApiAssertions from "../../definition/components/assertion/ApiAssertions";
import MsApiExtract from "../../definition/components/extract/ApiExtract";
import MsApiComponent from "./ApiComponent";
import {ELEMENTS, ELEMENT_TYPE} from "./Setting";
import MsApiCustomize from "./ApiCustomize";
import {getUUID, getCurrentProjectID} from "@/common/js/utils";
import ApiEnvironmentConfig from "../../definition/components/environment/ApiEnvironmentConfig";
import MsInputTag from "./MsInputTag";
import MsRun from "./DebugRun";
import MsLoopController from "./LoopController";
import MsApiScenarioComponent from "./ApiScenarioComponent";
import MsApiReportDetail from "../report/ApiReportDetail";
import MsVariableList from "./variable/VariableList";
import ApiImport from "../../definition/components/import/ApiImport";
@ -250,6 +223,7 @@
import OutsideClick from "@/common/js/outside-click";
import ScenarioApiRelevance from "./api/ApiRelevance";
import ScenarioRelevance from "./api/ScenarioRelevance";
import MsComponentConfig from "./component/ComponentConfig";
export default {
name: "EditApiScenario",
@ -264,17 +238,10 @@
ApiEnvironmentConfig,
MsApiReportDetail,
MsInputTag, MsRun,
MsApiScenarioComponent,
MsJsr233Processor,
MsConstantTimer,
MsIfController,
MsApiAssertions,
MsApiExtract,
MsApiComponent,
MsApiCustomize,
ApiImport,
InputTag,
MsLoopController,
MsComponentConfig,
},
data() {
return {
@ -458,6 +425,7 @@
//
this.editScenario();
}
this.reload();
},
showButton(...names) {
for (const name of names) {
@ -521,8 +489,9 @@
this.$refs.apiImport.open();
break;
}
this.selectedNode.expanded = true;
if (this.selectedNode) {
this.selectedNode.expanded = true;
}
this.sort();
},
nodeClick(data, node) {
@ -667,7 +636,12 @@
if (obj.name) {
obj.name = obj.name + '_copy';
}
hashTree.push(obj);
const index = hashTree.findIndex(d => d.resourceId === row.resourceId);
if (index != -1) {
hashTree.splice(index, 0, obj);
} else {
hashTree.push(obj);
}
this.sort();
this.reload();
}

View File

@ -24,6 +24,10 @@
<el-tag size="mini" style="margin-left: 20px" v-if="request.referenced==='Deleted'" type="danger">{{$t('api_test.automation.reference_deleted')}}</el-tag>
<el-tag size="mini" style="margin-left: 20px" v-if="request.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag>
<el-tag size="mini" style="margin-left: 20px" v-if="request.referenced ==='REF'">{{ $t('api_test.scenario.reference') }}</el-tag>
<ms-run :debug="false" :reportId="reportId" :run-data="runData"
@runRefresh="runRefresh" ref="runTest"/>
</template>
<template v-slot:button>
@ -56,22 +60,19 @@
{{$t('commons.save')}}
</el-button>
<ms-run :debug="false" :reportId="reportId" :run-data="runData"
@runRefresh="runRefresh" ref="runTest"/>
</api-base-component>
</template>
<script>
import MsSqlBasisParameters from "../../definition/components/request/database/BasisParameters";
import MsTcpBasisParameters from "../../definition/components/request/tcp/TcpBasisParameters";
import MsDubboBasisParameters from "../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../definition/components/request/http/ApiRequestForm";
import {REQ_METHOD} from "../../definition/model/JsonData";
import MsRequestResultTail from "../../definition/components/response/RequestResultTail";
import MsRun from "../../definition/components/Run";
import MsSqlBasisParameters from "../../../definition/components/request/database/BasisParameters";
import MsTcpBasisParameters from "../../../definition/components/request/tcp/TcpBasisParameters";
import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm";
import {REQ_METHOD} from "../../../definition/model/JsonData";
import MsRequestResultTail from "../../../definition/components/response/RequestResultTail";
import MsRun from "../../../definition/components/Run";
import {getUUID} from "@/common/js/utils";
import ApiBaseComponent from "./common/ApiBaseComponent";
import ApiBaseComponent from "../common/ApiBaseComponent";
export default {
name: "MsApiComponent",
props: {

View File

@ -28,11 +28,11 @@
</template>
<script>
import MsSqlBasisParameters from "../../definition/components/request/database/BasisParameters";
import MsTcpBasisParameters from "../../definition/components/request/tcp/TcpBasisParameters";
import MsDubboBasisParameters from "../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../definition/components/request/http/ApiRequestForm";
import ApiBaseComponent from "./common/ApiBaseComponent";
import MsSqlBasisParameters from "../../../definition/components/request/database/BasisParameters";
import MsTcpBasisParameters from "../../../definition/components/request/tcp/TcpBasisParameters";
import MsDubboBasisParameters from "../../../definition/components/request/dubbo/BasisParameters";
import MsApiRequestForm from "../../../definition/components/request/http/ApiHttpRequestForm";
import ApiBaseComponent from "../common/ApiBaseComponent";
export default {
name: "ApiScenarioComponent",

View File

@ -0,0 +1,113 @@
<template>
<div class="request-form">
<component :is="component" :scenario="scenario" :controller="scenario" :timer="scenario" :assertions="scenario" :extract="scenario" :jsr223-processor="scenario" :request="scenario" :currentScenario="currentScenario" :currentEnvironmentId="currentEnvironmentId" :node="node"
:draggable="true" :title="title" @suggestClick="suggestClick(node)" :response="response"
@remove="remove" @copyRow="copyRow"/>
</div>
</template>
<script>
import MsConstantTimer from "./ConstantTimer";
import MsIfController from "./IfController";
import {ELEMENT_TYPE} from "../Setting";
import MsJsr233Processor from "./Jsr233Processor";
import MsApiAssertions from "../../../definition/components/assertion/ApiAssertions";
import MsApiExtract from "../../../definition/components/extract/ApiExtract";
import MsApiComponent from "./ApiComponent";
import MsLoopController from "./LoopController";
import MsApiScenarioComponent from "./ApiScenarioComponent";
import {getUUID} from "@/common/js/utils";
export default {
name: "ComponentConfig",
components: {MsConstantTimer, MsIfController, MsJsr233Processor, MsApiAssertions, MsApiExtract, MsApiComponent, MsLoopController, MsApiScenarioComponent},
props: {
type: String,
scenario: {},
currentScenario: {},
currentEnvironmentId: String,
response: {},
node: {},
},
data() {
return {
title: this.$t('api_test.automation.customize_script'),
}
},
computed: {
component({type}) {
let name;
switch (type) {
case ELEMENT_TYPE.IfController:
name = "MsIfController";
break;
case ELEMENT_TYPE.ConstantTimer:
name = "MsConstantTimer";
break;
case ELEMENT_TYPE.JSR223Processor:
name = this.getComponent(ELEMENT_TYPE.JSR223Processor);
break;
case ELEMENT_TYPE.JSR223PreProcessor:
name = this.getComponent(ELEMENT_TYPE.JSR223PreProcessor);
break;
case ELEMENT_TYPE.JSR223PostProcessor:
name = this.getComponent(ELEMENT_TYPE.JSR223PostProcessor);
break;
case ELEMENT_TYPE.Assertions:
name = "MsApiAssertions";
break;
case ELEMENT_TYPE.Extract:
name = "MsApiExtract";
break;
case ELEMENT_TYPE.CustomizeReq:
name = "MsApiComponent";
break;
case ELEMENT_TYPE.LoopController:
name = "MsLoopController";
break;
case ELEMENT_TYPE.scenario:
name = "MsApiScenarioComponent";
break;
default:
name = "MsApiComponent";
break;
}
return name;
}
},
methods: {
getComponent(type) {
if (type === ELEMENT_TYPE.JSR223PreProcessor) {
this.title = this.$t('api_test.definition.request.pre_script');
return "MsJsr233Processor";
} else if (type === ELEMENT_TYPE.JSR223PostProcessor) {
this.title = this.$t('api_test.definition.request.post_script');
return "MsJsr233Processor";
} else {
this.title = this.$t('api_test.automation.customize_script');
return "MsJsr233Processor";
}
},
remove(row, node) {
this.$emit('remove',row,node);
},
copyRow(row, node) {
this.$emit('copyRow',row,node);
},
suggestClick(node) {
this.$emit('suggestClick',node);
},
}
}
</script>
<style scoped>
.request-form >>> .debug-button {
margin-left: auto;
display: block;
margin-right: 10px;
}
</style>

View File

@ -17,7 +17,7 @@
</template>
<script>
import ApiBaseComponent from "./common/ApiBaseComponent";
import ApiBaseComponent from "../common/ApiBaseComponent";
export default {
name: "MsConstantTimer",
components: {ApiBaseComponent},

View File

@ -25,7 +25,7 @@
</template>
<script>
import ApiBaseComponent from "./common/ApiBaseComponent";
import ApiBaseComponent from "../common/ApiBaseComponent";
export default {
name: "MsIfController",
components: {ApiBaseComponent},

View File

@ -35,10 +35,10 @@
</template>
<script>
import MsCodeEdit from "../../../common/components/MsCodeEdit";
import MsInstructionsIcon from "../../../common/components/MsInstructionsIcon";
import MsDropdown from "../../../common/components/MsDropdown";
import ApiBaseComponent from "./common/ApiBaseComponent";
import MsCodeEdit from "../../../../common/components/MsCodeEdit";
import MsInstructionsIcon from "../../../../common/components/MsInstructionsIcon";
import MsDropdown from "../../../../common/components/MsDropdown";
import ApiBaseComponent from "../common/ApiBaseComponent";
export default {
name: "MsJsr233Processor",

View File

@ -5,8 +5,8 @@
@remove="remove"
:data="controller"
:draggable="true"
color="#015478"
background-color="#E6EEF2"
color="#02A7F0"
background-color="#F4F4F5"
:title="$t('api_test.automation.loop_controller')">
<template v-slot:headerLeft>
@ -16,7 +16,6 @@
<el-radio @change="changeRadio" class="ms-radio" v-model="controller.loopType" label="WHILE">{{$t('loop.while')}}</el-radio>
</template>
<div v-if="controller.loopType==='LOOP_COUNT'" draggable>
<el-row>
<el-col :span="8">
@ -71,7 +70,7 @@
</template>
<script>
import ApiBaseComponent from "./common/ApiBaseComponent";
import ApiBaseComponent from "../common/ApiBaseComponent";
export default {
name: "MsLoopController",

View File

@ -15,20 +15,8 @@
</ms-aside-container>
<ms-main-container>
<el-dropdown size="small" split-button type="primary" class="ms-api-buttion"
@click="handleCommand('ADD')"
@command="handleCommand" v-tester>
{{ $t('commons.add') }}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="debug">{{ $t('api_test.definition.request.fast_debug') }}</el-dropdown-item>
<el-dropdown-item command="ADD">{{ $t('api_test.definition.request.title') }}</el-dropdown-item>
<el-dropdown-item command="CLOSE_ALL">{{ $t('api_test.definition.request.close_all_label') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<!-- 主框架列表 -->
<el-tabs v-model="apiDefaultTab" @edit="handleTabRemove">
<el-tabs v-model="apiDefaultTab" @edit="handleTabRemove" @tab-click="addTab">
<el-tab-pane v-for="(item) in apiTabs"
:key="item.name"
:label="item.title"
@ -98,313 +86,320 @@
@refresh="refresh" v-if="currentProtocol==='DUBBO'"/>
</div>
</el-tab-pane>
<el-tab-pane name="add">
<template v-slot:label>
<el-dropdown @command="handleCommand" v-tester>
<el-button type="primary" plain icon="el-icon-plus" size="mini" v-tester/>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="debug">{{ $t('api_test.definition.request.fast_debug') }}</el-dropdown-item>
<el-dropdown-item command="ADD">{{ $t('api_test.definition.request.title') }}</el-dropdown-item>
<el-dropdown-item command="CLOSE_ALL">{{ $t('api_test.definition.request.close_all_label') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-tab-pane>
</el-tabs>
</ms-main-container>
</ms-container>
</template>
<script>
import MsApiList from './components/list/ApiList';
import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer";
import MsAsideContainer from "../../common/components/MsAsideContainer";
import MsApiConfig from "./components/ApiConfig";
import MsDebugHttpPage from "./components/debug/DebugHttpPage";
import MsDebugJdbcPage from "./components/debug/DebugJdbcPage";
import MsDebugTcpPage from "./components/debug/DebugTcpPage";
import MsDebugDubboPage from "./components/debug/DebugDubboPage";
import MsApiList from './components/list/ApiList';
import MsContainer from "../../common/components/MsContainer";
import MsMainContainer from "../../common/components/MsMainContainer";
import MsAsideContainer from "../../common/components/MsAsideContainer";
import MsApiConfig from "./components/ApiConfig";
import MsDebugHttpPage from "./components/debug/DebugHttpPage";
import MsDebugJdbcPage from "./components/debug/DebugJdbcPage";
import MsDebugTcpPage from "./components/debug/DebugTcpPage";
import MsDebugDubboPage from "./components/debug/DebugDubboPage";
import MsRunTestHttpPage from "./components/runtest/RunTestHTTPPage";
import MsRunTestTcpPage from "./components/runtest/RunTestTCPPage";
import MsRunTestSqlPage from "./components/runtest/RunTestSQLPage";
import MsRunTestDubboPage from "./components/runtest/RunTestDubboPage";
import {downloadFile, getCurrentUser, getUUID, getCurrentProjectID} from "@/common/js/utils";
import MsApiModule from "./components/module/ApiModule";
import ApiCaseSimpleList from "./components/list/ApiCaseSimpleList";
import {PROJECT_NAME} from "../../../../common/js/constants";
import MsRunTestHttpPage from "./components/runtest/RunTestHTTPPage";
import MsRunTestTcpPage from "./components/runtest/RunTestTCPPage";
import MsRunTestSqlPage from "./components/runtest/RunTestSQLPage";
import MsRunTestDubboPage from "./components/runtest/RunTestDubboPage";
import {downloadFile, getCurrentUser, getUUID, getCurrentProjectID} from "@/common/js/utils";
import MsApiModule from "./components/module/ApiModule";
import ApiCaseSimpleList from "./components/list/ApiCaseSimpleList";
import {PROJECT_NAME} from "../../../../common/js/constants";
export default {
name: "ApiDefinition",
computed: {
queryDataType: function () {
let routeParam = this.$route.params.dataType;
let redirectIDParam = this.$route.params.redirectID;
this.changeRedirectParam(redirectIDParam);
if (routeParam === 'apiTestCase') {
this.isApiListEnableChange(false);
} else {
this.isApiListEnableChange(true);
}
return routeParam;
export default {
name: "ApiDefinition",
computed: {
queryDataType: function () {
let routeParam = this.$route.params.dataType;
let redirectIDParam = this.$route.params.redirectID;
this.changeRedirectParam(redirectIDParam);
if (routeParam === 'apiTestCase') {
this.isApiListEnableChange(false);
} else {
this.isApiListEnableChange(true);
}
return routeParam;
},
},
},
components: {
ApiCaseSimpleList,
MsApiModule,
MsApiList,
MsMainContainer,
MsContainer,
MsAsideContainer,
MsApiConfig,
MsDebugHttpPage,
MsRunTestHttpPage,
MsDebugJdbcPage,
MsDebugTcpPage,
MsDebugDubboPage,
MsRunTestTcpPage,
MsRunTestSqlPage,
MsRunTestDubboPage
},
props: {
visible: {
type: Boolean,
default: false,
components: {
ApiCaseSimpleList,
MsApiModule,
MsApiList,
MsMainContainer,
MsContainer,
MsAsideContainer,
MsApiConfig,
MsDebugHttpPage,
MsRunTestHttpPage,
MsDebugJdbcPage,
MsDebugTcpPage,
MsDebugDubboPage,
MsRunTestTcpPage,
MsRunTestSqlPage,
MsRunTestDubboPage
},
currentRow: {
type: Object,
}
},
data() {
return {
redirectID: '',
renderComponent: true,
selectDataRange: 'all',
showCasePage: true,
apiDefaultTab: 'default',
currentProtocol: null,
currentModule: null,
selectNodeIds: [],
currentApi: {},
moduleOptions: {},
trashEnable: false,
apiTabs: [{
title: this.$t('api_test.definition.api_title'),
name: 'default',
type: "list",
closable: false
}],
isApiListEnable: true
}
},
watch: {
currentProtocol() {
this.handleCommand("CLOSE_ALL");
},
redirectID() {
this.renderComponent = false;
this.$nextTick(() => {
// DOM my-component
this.renderComponent = true;
});
}
},
methods: {
changeRedirectParam(redirectIDParam) {
this.redirectID = redirectIDParam;
},
isApiListEnableChange(data) {
this.isApiListEnable = data;
},
handleCommand(e) {
switch (e) {
case "ADD":
this.handleTabAdd(e);
break;
case "TEST":
this.handleTabsEdit(this.$t("commons.api"), e);
break;
case "CLOSE_ALL":
this.handleTabClose();
break;
default:
this.handleTabsEdit(this.$t('api_test.definition.request.fast_debug'), "debug");
break;
props: {
visible: {
type: Boolean,
default: false,
},
currentRow: {
type: Object,
}
},
handleTabAdd(e) {
if (!getCurrentProjectID()) {
this.$warning(this.$t('commons.check_project_tip'));
return;
data() {
return {
redirectID: '',
renderComponent: true,
selectDataRange: 'all',
showCasePage: true,
apiDefaultTab: 'default',
currentProtocol: null,
currentModule: null,
selectNodeIds: [],
currentApi: {},
moduleOptions: {},
trashEnable: false,
apiTabs: [{
title: this.$t('api_test.definition.api_title'),
name: 'default',
type: "list",
closable: false
}],
isApiListEnable: true
}
let api = {
status: "Underway", method: "GET", userId: getCurrentUser().id,
url: "", protocol: this.currentProtocol, environmentId: ""
};
this.handleTabsEdit(this.$t('api_test.definition.request.title'), e, api);
},
handleTabClose() {
let tabs = this.apiTabs[0];
this.apiTabs = [];
this.apiDefaultTab = tabs.name;
this.apiTabs.push(tabs);
this.refresh();
},
handleTabRemove(targetName) {
let tabs = this.apiTabs;
let activeName = this.apiDefaultTab;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
watch: {
currentProtocol() {
this.handleCommand("CLOSE_ALL");
},
redirectID() {
this.renderComponent = false;
this.$nextTick(() => {
// DOM my-component
this.renderComponent = true;
});
}
this.apiDefaultTab = activeName;
this.apiTabs = tabs.filter(tab => tab.name !== targetName);
this.refresh();
},
//
createRootModel() {
this.$refs.nodeTree.createRootModel();
},
handleTabsEdit(targetName, action, api) {
if (!getCurrentProjectID()) {
this.$warning(this.$t('commons.check_project_tip'));
return;
}
if (targetName === undefined || targetName === null) {
targetName = this.$t('api_test.definition.request.title');
}
let newTabName = getUUID();
this.apiTabs.push({
title: targetName,
name: newTabName,
closable: true,
type: action,
api: api,
});
this.apiDefaultTab = newTabName;
},
debug(id) {
this.handleTabsEdit(this.$t('api_test.definition.request.fast_debug'), "debug", id);
},
editApi(row) {
let name = this.$t('api_test.definition.request.edit_api');
if (row.name) {
name = this.$t('api_test.definition.request.edit_api') + "-" + row.name;
}
this.handleTabsEdit(name, "ADD", row);
},
handleCase(api) {
this.currentApi = api;
this.showCasePage = false;
},
apiCaseClose() {
this.showCasePage = true;
},
exportAPI() {
if (!this.isApiListEnable) {
this.$warning('用例列表暂不支持导出,请切换成接口列表');
return;
}
let obj = {projectName: getCurrentProjectID(), protocol: this.currentProtocol}
if (this.$refs.apiList[0].selectRows && this.$refs.apiList[0].selectRows.size > 0) {
let arr = Array.from(this.$refs.apiList[0].selectRows);
obj.data = arr;
this.buildApiPath(obj.data);
downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
} else {
let condition = {};
let url = "/api/definition/list/all";
condition.filters = ["Prepare", "Underway", "Completed"];
condition.projectId = getCurrentProjectID();
this.$post(url, condition, response => {
obj.data = response.data;
methods: {
changeRedirectParam(redirectIDParam) {
this.redirectID = redirectIDParam;
},
isApiListEnableChange(data) {
this.isApiListEnable = data;
},
addTab(tab) {
if (tab.name === 'add') {
this.handleCommand("ADD");
}
},
handleCommand(e) {
switch (e) {
case "ADD":
this.handleTabAdd(e);
break;
case "TEST":
this.handleTabsEdit(this.$t("commons.api"), e);
break;
case "CLOSE_ALL":
this.handleTabClose();
break;
default:
this.handleTabsEdit(this.$t('api_test.definition.request.fast_debug'), "debug");
break;
}
},
handleTabAdd(e) {
if (!getCurrentProjectID()) {
this.$warning(this.$t('commons.check_project_tip'));
return;
}
let api = {
status: "Underway", method: "GET", userId: getCurrentUser().id,
url: "", protocol: this.currentProtocol, environmentId: ""
};
this.handleTabsEdit(this.$t('api_test.definition.request.title'), e, api);
},
handleTabClose() {
let tabs = this.apiTabs[0];
this.apiTabs = [];
this.apiDefaultTab = tabs.name;
this.apiTabs.push(tabs);
this.refresh();
},
handleTabRemove(targetName) {
let tabs = this.apiTabs;
let activeName = this.apiDefaultTab;
if (activeName === targetName) {
tabs.forEach((tab, index) => {
if (tab.name === targetName) {
let nextTab = tabs[index + 1] || tabs[index - 1];
if (nextTab) {
activeName = nextTab.name;
}
}
});
}
this.apiDefaultTab = activeName;
this.apiTabs = tabs.filter(tab => tab.name !== targetName);
this.refresh();
},
//
createRootModel() {
this.$refs.nodeTree.createRootModel();
},
handleTabsEdit(targetName, action, api) {
if (!getCurrentProjectID()) {
this.$warning(this.$t('commons.check_project_tip'));
return;
}
if (targetName === undefined || targetName === null) {
targetName = this.$t('api_test.definition.request.title');
}
let newTabName = getUUID();
this.apiTabs.push({
title: targetName,
name: newTabName,
closable: true,
type: action,
api: api,
});
this.apiDefaultTab = newTabName;
},
debug(id) {
this.handleTabsEdit(this.$t('api_test.definition.request.fast_debug'), "debug", id);
},
editApi(row) {
let name = this.$t('api_test.definition.request.edit_api');
if (row.name) {
name = this.$t('api_test.definition.request.edit_api') + "-" + row.name;
}
this.handleTabsEdit(name, "ADD", row);
},
handleCase(api) {
this.currentApi = api;
this.showCasePage = false;
},
apiCaseClose() {
this.showCasePage = true;
},
exportAPI() {
if (!this.isApiListEnable) {
this.$warning('用例列表暂不支持导出,请切换成接口列表');
return;
}
let obj = {projectName: getCurrentProjectID(), protocol: this.currentProtocol}
if (this.$refs.apiList[0].selectRows && this.$refs.apiList[0].selectRows.size > 0) {
let arr = Array.from(this.$refs.apiList[0].selectRows);
obj.data = arr;
this.buildApiPath(obj.data);
downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
});
}
},
buildApiPath(apis) {
apis.forEach((api) => {
this.moduleOptions.forEach(item => {
if (api.moduleId === item.id) {
api.modulePath = item.path;
}
});
});
},
refresh(data) {
this.$refs.apiList[0].initTable(data);
},
setTabTitle(data) {
for (let index in this.apiTabs) {
let tab = this.apiTabs[index];
if (tab.name === this.apiDefaultTab) {
tab.title = this.$t('api_test.definition.request.edit_api') + "-" + data.name;
break;
} else {
let condition = {};
let url = "/api/definition/list/all";
condition.filters = ["Prepare", "Underway", "Completed"];
condition.projectId = getCurrentProjectID();
this.$post(url, condition, response => {
obj.data = response.data;
this.buildApiPath(obj.data);
downloadFile("Metersphere_Api_" + localStorage.getItem(PROJECT_NAME) + ".json", JSON.stringify(obj));
});
}
}
},
runTest(data) {
this.setTabTitle(data);
this.handleTabsEdit(this.$t("commons.api"), "TEST", data);
},
saveApi(data) {
this.setTabTitle(data);
this.refresh(data);
},
},
buildApiPath(apis) {
apis.forEach((api) => {
this.moduleOptions.forEach(item => {
if (api.moduleId === item.id) {
api.modulePath = item.path;
}
});
});
},
refresh(data) {
this.$refs.apiList[0].initTable(data);
},
setTabTitle(data) {
for (let index in this.apiTabs) {
let tab = this.apiTabs[index];
if (tab.name === this.apiDefaultTab) {
tab.title = this.$t('api_test.definition.request.edit_api') + "-" + data.name;
break;
}
}
},
runTest(data) {
this.setTabTitle(data);
this.handleTabsEdit(this.$t("commons.api"), "TEST", data);
},
saveApi(data) {
this.setTabTitle(data);
this.refresh(data);
},
showExecResult(row) {
this.debug(row);
},
nodeChange(node, nodeIds, pNodes) {
this.selectNodeIds = nodeIds;
},
handleProtocolChange(protocol) {
this.currentProtocol = protocol;
},
setModuleOptions(data) {
this.moduleOptions = data;
},
changeSelectDataRangeAll(tableType) {
this.$route.params.dataSelectRange = 'all';
},
enableTrash(data) {
this.trashEnable = data;
showExecResult(row) {
this.debug(row);
},
nodeChange(node, nodeIds, pNodes) {
this.selectNodeIds = nodeIds;
},
handleProtocolChange(protocol) {
this.currentProtocol = protocol;
},
setModuleOptions(data) {
this.moduleOptions = data;
},
changeSelectDataRangeAll(tableType) {
this.$route.params.dataSelectRange = 'all';
},
enableTrash(data) {
this.trashEnable = data;
}
}
}
}
</script>
<style scoped>
.ms-api-buttion {
position: absolute;
top: 100px;
right: 4px;
padding: 0;
background: 0 0;
border: none;
outline: 0;
cursor: pointer;
margin-right: 10px;
font-size: 16px;
}
.ms-api-div {
overflow-y: auto;
height: calc(100vh - 155px)
}
.ms-api-div {
overflow-y: auto;
height: calc(100vh - 155px)
}
/deep/ .el-tabs__header {
margin: 0 0 5px;
width: calc(100% - 90px);
}
/deep/ .el-main {
overflow: hidden;
}
/deep/ .el-main {
overflow: hidden;
}
/deep/ .el-tabs__header {
margin: 0 0 0px;
/*width: calc(100% - 90px);*/
}
/deep/ .el-card {
/*border: 1px solid #EBEEF5;*/
/*border-style: none;*/
border-top: none;
}
/deep/ .el-card {
/*border: 1px solid #EBEEF5;*/
/*border-style: none;*/
border-top: none;
}
/deep/ .api-component {
margin-top: 10px;
}
/deep/ .api-component {
margin-top: 10px;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div></div>
<span></span>
</template>
<script>
import {getUUID, getBodyUploadFiles} from "@/common/js/utils";
@ -68,9 +68,9 @@
let bodyFiles = getBodyUploadFiles(reqObj, this.runData);
let url = "";
if (this.debug) {
reqObj.reportId = this.reportId;
url = "/api/definition/run/debug";
} else {
reqObj.reportId = "run";
url = "/api/definition/run";
}
this.$fileUpload(url, null, bodyFiles, reqObj, response => {

View File

@ -57,7 +57,7 @@
<script>
import {AssertionJSR223} from "../../model/ApiTestModel";
import MsDialogFooter from "@/business/components/common/components/MsDialogFooter";
import MsJsr233Processor from "../../../automation/scenario/Jsr233Processor";
import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor";
export default {
name: "MsApiAssertionJsr223",

View File

@ -55,7 +55,7 @@
import MsApiAssertionText from "./ApiAssertionText";
import MsApiAssertionRegex from "./ApiAssertionRegex";
import MsApiAssertionDuration from "./ApiAssertionDuration";
import {ASSERTION_TYPE, JSONPath, Scenario} from "../../model/ApiTestModel";
import {ASSERTION_TYPE, JSONPath} from "../../model/ApiTestModel";
import MsApiAssertionsEdit from "./ApiAssertionsEdit";
import MsApiAssertionJsonPath from "./ApiAssertionJsonPath";
import MsApiAssertionJsr223 from "./ApiAssertionJsr223";
@ -91,7 +91,6 @@
type: String,
default: "margin-top: 10px"
},
scenario: Scenario,
isReadOnly: {
type: Boolean,
default: false

View File

@ -25,17 +25,13 @@
{{ $t('api_test.definition.request.body_binary') }}
</el-radio>
</el-radio-group>
<el-row v-if="body.type == 'Form Data' || body.type == 'WWW_FORM'">
<el-link class="ms-el-link" @click="batchAdd"> {{$t("commons.batch_add")}}</el-link>
</el-row>
<div style="min-width: 1200px;" v-if="body.type == 'Form Data' || body.type == 'WWW_FORM'">
<el-row v-if="body.type == 'Form Data' || body.type == 'WWW_FORM'">
<el-link class="ms-el-link" @click="batchAdd"> {{$t("commons.batch_add")}}</el-link>
</el-row>
<ms-api-variable :is-read-only="isReadOnly"
:parameters="body.kvs"
:isShowEnable="isShowEnable" type="body" v-if="body.type == 'Form Data'"/>
<ms-api-from-url-variable :is-read-only="isReadOnly"
:parameters="body.kvs"
type="body" v-if="body.type == 'WWW_FORM'"/>
:isShowEnable="isShowEnable" type="body"/>
</div>
<div v-if="body.type == 'JSON'">
<div style="padding: 10px">

View File

@ -67,10 +67,10 @@
<div v-if="apiCase.active">
<p class="tip">{{ $t('api_test.definition.request.req_param') }} </p>
<ms-api-request-form :is-read-only="isReadOnly" :headers="apiCase.request.headers " :request="apiCase.request" v-if="api.protocol==='HTTP'"/>
<ms-tcp-basis-parameters :request="apiCase.request" v-if="api.protocol==='TCP'"/>
<ms-sql-basis-parameters :request="apiCase.request" v-if="api.protocol==='SQL'"/>
<ms-dubbo-basis-parameters :request="apiCase.request" v-if="api.protocol==='DUBBO'"/>
<ms-api-request-form :showScript="true" :is-read-only="isReadOnly" :headers="apiCase.request.headers " :request="apiCase.request" v-if="api.protocol==='HTTP'"/>
<ms-tcp-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='TCP'"/>
<ms-sql-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='SQL'"/>
<ms-dubbo-basis-parameters :showScript="true" :request="apiCase.request" v-if="api.protocol==='DUBBO'"/>
<!-- HTTP 请求返回数据 -->
<p class="tip">
@ -92,11 +92,11 @@
</template>
<script>
import {getCurrentProjectID, getUUID} from "../../../../../../common/js/utils";
import {_getBodyUploadFiles, getCurrentProjectID} from "../../../../../../common/js/utils";
import {PRIORITY, RESULT_MAP} from "../../model/JsonData";
import MsTag from "../../../../common/components/MsTag";
import MsTipButton from "../../../../common/components/MsTipButton";
import MsApiRequestForm from "../request/http/ApiRequestForm";
import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
import ApiEnvironmentConfig from "../environment/ApiEnvironmentConfig";
import MsApiAssertions from "../assertion/ApiAssertions";
import MsSqlBasisParameters from "../request/database/BasisParameters";
@ -188,13 +188,14 @@
}
},
singleRun(data) {
data.message = true;
this.saveTestCase(data);
this.$emit('singleRun', data);
},
copyCase(data) {
let obj = {name: "copy_" + data.name, priority: data.priority, active: true, request: data.request};
this.$emit('copyCase', obj);
},
selectTestCase(item, $event) {
if (!item.id || !this.loaded) {
return;
@ -210,7 +211,6 @@
$event.currentTarget.className = "el-card is-always-shadow is-selected";
this.$emit('selectTestCase', item);
}
},
changePriority(row) {
if (row.id) {
@ -223,6 +223,7 @@
if (this.validate(tmp)) {
return;
}
tmp.request.body = row.request.body;
let bodyFiles = this.getBodyUploadFiles(tmp);
tmp.projectId = getCurrentProjectID();
tmp.active = true;
@ -241,7 +242,9 @@
row.id = data.id;
row.createTime = data.createTime;
row.updateTime = data.updateTime;
this.$success(this.$t('commons.save_success'));
if (!row.message) {
this.$success(this.$t('commons.save_success'));
}
});
},
showInput(row) {
@ -278,37 +281,7 @@
getBodyUploadFiles(row) {
let bodyUploadFiles = [];
row.bodyUploadIds = [];
let request = row.request;
if (request.body && request.body.kvs) {
request.body.kvs.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
row.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
if (request.body.binary) {
request.body.binary.forEach(param => {
if (param.files) {
param.files.forEach(item => {
if (item.file) {
let fileId = getUUID().substring(0, 8);
item.name = item.file.name;
item.id = fileId;
row.bodyUploadIds.push(fileId);
bodyUploadFiles.push(item.file);
}
});
}
});
}
}
_getBodyUploadFiles(row.request, bodyUploadFiles, row);
return bodyUploadFiles;
},
}

View File

@ -108,13 +108,14 @@
</template>
<script>
import MsApiRequestForm from "../request/http/ApiRequestForm";
import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
import MsResponseText from "../response/ResponseText";
import {WORKSPACE_ID} from '../../../../../../common/js/constants';
import {API_STATUS, REQ_METHOD} from "../../model/JsonData";
import {KeyValue} from "../../model/ApiTestModel";
import MsInputTag from "@/business/components/api/automation/scenario/MsInputTag";
import MsJsr233Processor from "../../../automation/scenario/Jsr233Processor";
import MsJsr233Processor from "../../../automation/scenario/component/Jsr233Processor";
export default {
name: "MsAddCompleteHttpApi",

View File

@ -29,7 +29,6 @@
</template>
<script>
import MsApiRequestForm from "../request/http/ApiRequestForm";
import MsResponseResult from "../response/ResponseResult";
import MsRequestMetric from "../response/RequestMetric";
import {getUUID, getCurrentUser} from "@/common/js/utils";
@ -42,7 +41,7 @@
export default {
name: "ApiConfig",
components: {MsRequestResultTail, MsResponseResult, MsApiRequestForm, MsRequestMetric, MsResponseText, MsRun, MsBasisParameters},
components: {MsRequestResultTail, MsResponseResult, MsRequestMetric, MsResponseText, MsRun, MsBasisParameters},
props: {
currentProtocol: String,
scenario: Boolean,

View File

@ -44,7 +44,7 @@
</template>
<script>
import MsApiRequestForm from "../request/http/ApiRequestForm";
import MsApiRequestForm from "../request/http/ApiHttpRequestForm";
import MsResponseResult from "../response/ResponseResult";
import MsRequestMetric from "../response/RequestMetric";
import {getUUID, getCurrentUser} from "@/common/js/utils";

Some files were not shown because too many files have changed in this diff Show More