diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java b/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java index a9904784cb..ff4f5128c5 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/RunScenarioRequest.java @@ -23,6 +23,9 @@ public class RunScenarioRequest { private String runMode; + //测试情景和测试计划的关联ID + private String planScenarioId; + private List planCaseIds; private String reportUserID; diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/SchedulePlanScenarioExecuteRequest.java b/backend/src/main/java/io/metersphere/api/dto/automation/SchedulePlanScenarioExecuteRequest.java new file mode 100644 index 0000000000..293ca46f2f --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/automation/SchedulePlanScenarioExecuteRequest.java @@ -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 planCaseIds; + + private String reportUserID; + + //key: test_plan.id, value: test_plan_api_scenario <->scenarioValue + private Map> testPlanScenarioIDMap; + + private String testPlanReportId; +} diff --git a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java index 870ed44bea..914afd2eff 100644 --- a/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java +++ b/backend/src/main/java/io/metersphere/api/jmeter/APIBackendListenerClient.java @@ -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) { @@ -169,10 +176,19 @@ public class APIBackendListenerClient extends AbstractBackendListenerClient impl 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 testPlanReportIdList = new ArrayList<>(); + testPlanReportIdList.add(debugReportId); + testPlanReportService.updateReport(testPlanReportIdList,ApiRunMode.SCHEDULE_API_PLAN.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); diff --git a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java index 3a03fcf18d..f5354ed9e8 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -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> testPlanScenarioIdMap = request.getTestPlanScenarioIDMap(); + for (Map.Entry> entry : testPlanScenarioIdMap.entrySet()) { + String testPlanID = entry.getKey(); + Map planScenarioIdMap = entry.getValue(); + List 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 elements = mapper.readValue(element.getString("hashTree"), + new TypeReference>() { + }); + scenario.setHashTree(elements); + } + if (StringUtils.isNotEmpty(element.getString("variables"))) { + LinkedList variables = mapper.readValue(element.getString("variables"), + new TypeReference>() { + }); + scenario.setVariables(variables); + } + group.setEnableCookieShare(scenario.isEnableCookieShare()); + LinkedList 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 getAllScenarioIdsByFontedSelect(List moduleIds, String name, String projectId, List filters, List unSelectIds) { + ApiScenarioRequest selectRequest = new ApiScenarioRequest(); + selectRequest.setModuleIds(moduleIds); + selectRequest.setName(name); + selectRequest.setProjectId(projectId); + selectRequest.setFilters(filters); + selectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId()); + List list = extApiScenarioMapper.list(selectRequest); + List allIds = list.stream().map(ApiScenarioDTO::getId).collect(Collectors.toList()); + List 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 getAllScenarioIdsByFontedSelect(List moduleIds, String name, String projectId, List filters, List unSelectIds) { - ApiScenarioRequest selectRequest = new ApiScenarioRequest(); - selectRequest.setModuleIds(moduleIds); - selectRequest.setName(name); - selectRequest.setProjectId(projectId); - selectRequest.setFilters(filters); - selectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId()); - List list = extApiScenarioMapper.list(selectRequest); - List allIds = list.stream().map(ApiScenarioDTO::getId).collect(Collectors.toList()); - List ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList()); - return ids; - } public String addScenarioToPlan(SaveApiPlanRequest request) { if (CollectionUtils.isEmpty(request.getPlanIds())) { diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java index 77f3b87ce0..3689eca69b 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionExecResultService.java @@ -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); diff --git a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java index bfe437de64..049ef6fc1a 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -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; @@ -334,63 +337,14 @@ public class ApiDefinitionService { if (StringUtils.isNotBlank(request.getType()) && StringUtils.equals(request.getType(), ApiRunMode.API_PLAN.name())) { runMode = ApiRunMode.API_PLAN.name(); } + + MsTestPlan testPlan = new MsTestPlan(); + System.out.println(testPlan.getJmx(hashTree)); // 调用执行方法 jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), runMode); 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 elements = mapper.readValue(element.getString("hashTree"), - new TypeReference>() { - }); - scenario.setHashTree(elements); - } - if (StringUtils.isNotEmpty(element.getString("variables"))) { - LinkedList variables = mapper.readValue(element.getString("variables"), - new TypeReference>() { - }); - scenario.setVariables(variables); - } - group.setEnableCookieShare(scenario.isEnableCookieShare()); - LinkedList 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)); diff --git a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java index 8313835e75..aa4c1a6d43 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiScenarioReportService.java @@ -17,10 +17,12 @@ import io.metersphere.base.mapper.TestPlanApiScenarioMapper; import io.metersphere.base.mapper.ext.ExtApiScenarioReportMapper; import io.metersphere.commons.constants.ApiRunMode; 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 +30,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 +49,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 +160,65 @@ public class ApiScenarioReportService { return report; } + public ApiScenarioReport updateSchedulePlanCase(TestResult result) { + ApiScenarioReport lastReport = null; + List scenarioResultList = result.getScenarios(); + + List 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 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()); + + return lastReport; + } public ApiScenarioReport updateScenario(TestResult result) { ApiScenarioReport lastReport = null; for (ScenarioResult item : result.getScenarios()) { diff --git a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java index 78875cf026..f2026aada5 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java @@ -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() { - }); - if(StringUtils.isBlank(request.getEnvironmentId())){ - TestPlanApiCaseExample example = new TestPlanApiCaseExample(); - example.createCriteria().andTestPlanIdEqualTo(request.getTestPlanId()).andApiCaseIdEqualTo(request.getCaseId()); - List 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 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() { + }); + if(StringUtils.isBlank(request.getEnvironmentId())){ + TestPlanApiCaseExample example = new TestPlanApiCaseExample(); + example.createCriteria().andTestPlanIdEqualTo(request.getTestPlanId()).andApiCaseIdEqualTo(request.getCaseId()); + List 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 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){ ApiDefinitionExecResultExample apidefinitionexecresultexample = new ApiDefinitionExecResultExample(); diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanReport.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanReport.java new file mode 100644 index 0000000000..400afde08b --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanReport.java @@ -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; +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanReportData.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportData.java new file mode 100644 index 0000000000..783f13d447 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportData.java @@ -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; +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanReportDataExample.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportDataExample.java new file mode 100644 index 0000000000..63f0706282 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportDataExample.java @@ -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 oredCriteria; + + public TestPlanReportDataExample() { + oredCriteria = new ArrayList(); + } + + 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 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 criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List 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 values) { + addCriterion("id in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdNotIn(List 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 values) { + addCriterion("test_plan_report_id in", values, "testPlanReportId"); + return (Criteria) this; + } + + public Criteria andTestPlanReportIdNotIn(List 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); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanReportDataWithBLOBs.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportDataWithBLOBs.java new file mode 100644 index 0000000000..8c5a993f23 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportDataWithBLOBs.java @@ -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; +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanReportExample.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportExample.java new file mode 100644 index 0000000000..43d54d3133 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanReportExample.java @@ -0,0 +1,1110 @@ +package io.metersphere.base.domain; + +import java.util.ArrayList; +import java.util.List; + +public class TestPlanReportExample { + protected String orderByClause; + + protected boolean distinct; + + protected List oredCriteria; + + public TestPlanReportExample() { + oredCriteria = new ArrayList(); + } + + 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 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 criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List 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 values) { + addCriterion("id in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdNotIn(List 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 andTestPlanIdIsNull() { + addCriterion("test_plan_id is null"); + return (Criteria) this; + } + + public Criteria andTestPlanIdIsNotNull() { + addCriterion("test_plan_id is not null"); + return (Criteria) this; + } + + public Criteria andTestPlanIdEqualTo(String value) { + addCriterion("test_plan_id =", value, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdNotEqualTo(String value) { + addCriterion("test_plan_id <>", value, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdGreaterThan(String value) { + addCriterion("test_plan_id >", value, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdGreaterThanOrEqualTo(String value) { + addCriterion("test_plan_id >=", value, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdLessThan(String value) { + addCriterion("test_plan_id <", value, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdLessThanOrEqualTo(String value) { + addCriterion("test_plan_id <=", value, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdLike(String value) { + addCriterion("test_plan_id like", value, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdNotLike(String value) { + addCriterion("test_plan_id not like", value, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdIn(List values) { + addCriterion("test_plan_id in", values, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdNotIn(List values) { + addCriterion("test_plan_id not in", values, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdBetween(String value1, String value2) { + addCriterion("test_plan_id between", value1, value2, "testPlanId"); + return (Criteria) this; + } + + public Criteria andTestPlanIdNotBetween(String value1, String value2) { + addCriterion("test_plan_id not between", value1, value2, "testPlanId"); + return (Criteria) this; + } + + public Criteria andCreateTimeIsNull() { + addCriterion("create_time is null"); + return (Criteria) this; + } + + public Criteria andCreateTimeIsNotNull() { + addCriterion("create_time is not null"); + return (Criteria) this; + } + + public Criteria andCreateTimeEqualTo(Long value) { + addCriterion("create_time =", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotEqualTo(Long value) { + addCriterion("create_time <>", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeGreaterThan(Long value) { + addCriterion("create_time >", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeGreaterThanOrEqualTo(Long value) { + addCriterion("create_time >=", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeLessThan(Long value) { + addCriterion("create_time <", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeLessThanOrEqualTo(Long value) { + addCriterion("create_time <=", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeIn(List values) { + addCriterion("create_time in", values, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotIn(List values) { + addCriterion("create_time not in", values, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeBetween(Long value1, Long value2) { + addCriterion("create_time between", value1, value2, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotBetween(Long value1, Long value2) { + addCriterion("create_time not between", value1, value2, "createTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeIsNull() { + addCriterion("update_time is null"); + return (Criteria) this; + } + + public Criteria andUpdateTimeIsNotNull() { + addCriterion("update_time is not null"); + return (Criteria) this; + } + + public Criteria andUpdateTimeEqualTo(Long value) { + addCriterion("update_time =", value, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeNotEqualTo(Long value) { + addCriterion("update_time <>", value, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeGreaterThan(Long value) { + addCriterion("update_time >", value, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeGreaterThanOrEqualTo(Long value) { + addCriterion("update_time >=", value, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeLessThan(Long value) { + addCriterion("update_time <", value, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeLessThanOrEqualTo(Long value) { + addCriterion("update_time <=", value, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeIn(List values) { + addCriterion("update_time in", values, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeNotIn(List values) { + addCriterion("update_time not in", values, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeBetween(Long value1, Long value2) { + addCriterion("update_time between", value1, value2, "updateTime"); + return (Criteria) this; + } + + public Criteria andUpdateTimeNotBetween(Long value1, Long value2) { + addCriterion("update_time not between", value1, value2, "updateTime"); + return (Criteria) this; + } + + public Criteria andNameIsNull() { + addCriterion("`name` is null"); + return (Criteria) this; + } + + public Criteria andNameIsNotNull() { + addCriterion("`name` is not null"); + return (Criteria) this; + } + + public Criteria andNameEqualTo(String value) { + addCriterion("`name` =", value, "name"); + return (Criteria) this; + } + + public Criteria andNameNotEqualTo(String value) { + addCriterion("`name` <>", value, "name"); + return (Criteria) this; + } + + public Criteria andNameGreaterThan(String value) { + addCriterion("`name` >", value, "name"); + return (Criteria) this; + } + + public Criteria andNameGreaterThanOrEqualTo(String value) { + addCriterion("`name` >=", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLessThan(String value) { + addCriterion("`name` <", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLessThanOrEqualTo(String value) { + addCriterion("`name` <=", value, "name"); + return (Criteria) this; + } + + public Criteria andNameLike(String value) { + addCriterion("`name` like", value, "name"); + return (Criteria) this; + } + + public Criteria andNameNotLike(String value) { + addCriterion("`name` not like", value, "name"); + return (Criteria) this; + } + + public Criteria andNameIn(List values) { + addCriterion("`name` in", values, "name"); + return (Criteria) this; + } + + public Criteria andNameNotIn(List values) { + addCriterion("`name` not in", values, "name"); + return (Criteria) this; + } + + public Criteria andNameBetween(String value1, String value2) { + addCriterion("`name` between", value1, value2, "name"); + return (Criteria) this; + } + + public Criteria andNameNotBetween(String value1, String value2) { + addCriterion("`name` not between", value1, value2, "name"); + return (Criteria) this; + } + + public Criteria andStatusIsNull() { + addCriterion("`status` is null"); + return (Criteria) this; + } + + public Criteria andStatusIsNotNull() { + addCriterion("`status` is not null"); + return (Criteria) this; + } + + public Criteria andStatusEqualTo(String value) { + addCriterion("`status` =", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotEqualTo(String value) { + addCriterion("`status` <>", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusGreaterThan(String value) { + addCriterion("`status` >", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusGreaterThanOrEqualTo(String value) { + addCriterion("`status` >=", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLessThan(String value) { + addCriterion("`status` <", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLessThanOrEqualTo(String value) { + addCriterion("`status` <=", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLike(String value) { + addCriterion("`status` like", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotLike(String value) { + addCriterion("`status` not like", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusIn(List values) { + addCriterion("`status` in", values, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotIn(List values) { + addCriterion("`status` not in", values, "status"); + return (Criteria) this; + } + + public Criteria andStatusBetween(String value1, String value2) { + addCriterion("`status` between", value1, value2, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotBetween(String value1, String value2) { + addCriterion("`status` not between", value1, value2, "status"); + return (Criteria) this; + } + + public Criteria andTriggerModeIsNull() { + addCriterion("trigger_mode is null"); + return (Criteria) this; + } + + public Criteria andTriggerModeIsNotNull() { + addCriterion("trigger_mode is not null"); + return (Criteria) this; + } + + public Criteria andTriggerModeEqualTo(String value) { + addCriterion("trigger_mode =", value, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeNotEqualTo(String value) { + addCriterion("trigger_mode <>", value, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeGreaterThan(String value) { + addCriterion("trigger_mode >", value, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeGreaterThanOrEqualTo(String value) { + addCriterion("trigger_mode >=", value, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeLessThan(String value) { + addCriterion("trigger_mode <", value, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeLessThanOrEqualTo(String value) { + addCriterion("trigger_mode <=", value, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeLike(String value) { + addCriterion("trigger_mode like", value, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeNotLike(String value) { + addCriterion("trigger_mode not like", value, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeIn(List values) { + addCriterion("trigger_mode in", values, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeNotIn(List values) { + addCriterion("trigger_mode not in", values, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeBetween(String value1, String value2) { + addCriterion("trigger_mode between", value1, value2, "triggerMode"); + return (Criteria) this; + } + + public Criteria andTriggerModeNotBetween(String value1, String value2) { + addCriterion("trigger_mode not between", value1, value2, "triggerMode"); + return (Criteria) this; + } + + public Criteria andCreatorIsNull() { + addCriterion("creator is null"); + return (Criteria) this; + } + + public Criteria andCreatorIsNotNull() { + addCriterion("creator is not null"); + return (Criteria) this; + } + + public Criteria andCreatorEqualTo(String value) { + addCriterion("creator =", value, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorNotEqualTo(String value) { + addCriterion("creator <>", value, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorGreaterThan(String value) { + addCriterion("creator >", value, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorGreaterThanOrEqualTo(String value) { + addCriterion("creator >=", value, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorLessThan(String value) { + addCriterion("creator <", value, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorLessThanOrEqualTo(String value) { + addCriterion("creator <=", value, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorLike(String value) { + addCriterion("creator like", value, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorNotLike(String value) { + addCriterion("creator not like", value, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorIn(List values) { + addCriterion("creator in", values, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorNotIn(List values) { + addCriterion("creator not in", values, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorBetween(String value1, String value2) { + addCriterion("creator between", value1, value2, "creator"); + return (Criteria) this; + } + + public Criteria andCreatorNotBetween(String value1, String value2) { + addCriterion("creator not between", value1, value2, "creator"); + return (Criteria) this; + } + + public Criteria andStartTimeIsNull() { + addCriterion("start_time is null"); + return (Criteria) this; + } + + public Criteria andStartTimeIsNotNull() { + addCriterion("start_time is not null"); + return (Criteria) this; + } + + public Criteria andStartTimeEqualTo(Long value) { + addCriterion("start_time =", value, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeNotEqualTo(Long value) { + addCriterion("start_time <>", value, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeGreaterThan(Long value) { + addCriterion("start_time >", value, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeGreaterThanOrEqualTo(Long value) { + addCriterion("start_time >=", value, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeLessThan(Long value) { + addCriterion("start_time <", value, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeLessThanOrEqualTo(Long value) { + addCriterion("start_time <=", value, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeIn(List values) { + addCriterion("start_time in", values, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeNotIn(List values) { + addCriterion("start_time not in", values, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeBetween(Long value1, Long value2) { + addCriterion("start_time between", value1, value2, "startTime"); + return (Criteria) this; + } + + public Criteria andStartTimeNotBetween(Long value1, Long value2) { + addCriterion("start_time not between", value1, value2, "startTime"); + return (Criteria) this; + } + + public Criteria andEndTimeIsNull() { + addCriterion("end_time is null"); + return (Criteria) this; + } + + public Criteria andEndTimeIsNotNull() { + addCriterion("end_time is not null"); + return (Criteria) this; + } + + public Criteria andEndTimeEqualTo(Long value) { + addCriterion("end_time =", value, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeNotEqualTo(Long value) { + addCriterion("end_time <>", value, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeGreaterThan(Long value) { + addCriterion("end_time >", value, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeGreaterThanOrEqualTo(Long value) { + addCriterion("end_time >=", value, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeLessThan(Long value) { + addCriterion("end_time <", value, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeLessThanOrEqualTo(Long value) { + addCriterion("end_time <=", value, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeIn(List values) { + addCriterion("end_time in", values, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeNotIn(List values) { + addCriterion("end_time not in", values, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeBetween(Long value1, Long value2) { + addCriterion("end_time between", value1, value2, "endTime"); + return (Criteria) this; + } + + public Criteria andEndTimeNotBetween(Long value1, Long value2) { + addCriterion("end_time not between", value1, value2, "endTime"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingIsNull() { + addCriterion("is_api_case_executing is null"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingIsNotNull() { + addCriterion("is_api_case_executing is not null"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingEqualTo(Byte value) { + addCriterion("is_api_case_executing =", value, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingNotEqualTo(Byte value) { + addCriterion("is_api_case_executing <>", value, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingGreaterThan(Byte value) { + addCriterion("is_api_case_executing >", value, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingGreaterThanOrEqualTo(Byte value) { + addCriterion("is_api_case_executing >=", value, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingLessThan(Byte value) { + addCriterion("is_api_case_executing <", value, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingLessThanOrEqualTo(Byte value) { + addCriterion("is_api_case_executing <=", value, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingIn(List values) { + addCriterion("is_api_case_executing in", values, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingNotIn(List values) { + addCriterion("is_api_case_executing not in", values, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingBetween(Byte value1, Byte value2) { + addCriterion("is_api_case_executing between", value1, value2, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsApiCaseExecutingNotBetween(Byte value1, Byte value2) { + addCriterion("is_api_case_executing not between", value1, value2, "isApiCaseExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingIsNull() { + addCriterion("is_scenario_executing is null"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingIsNotNull() { + addCriterion("is_scenario_executing is not null"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingEqualTo(Byte value) { + addCriterion("is_scenario_executing =", value, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingNotEqualTo(Byte value) { + addCriterion("is_scenario_executing <>", value, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingGreaterThan(Byte value) { + addCriterion("is_scenario_executing >", value, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingGreaterThanOrEqualTo(Byte value) { + addCriterion("is_scenario_executing >=", value, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingLessThan(Byte value) { + addCriterion("is_scenario_executing <", value, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingLessThanOrEqualTo(Byte value) { + addCriterion("is_scenario_executing <=", value, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingIn(List values) { + addCriterion("is_scenario_executing in", values, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingNotIn(List values) { + addCriterion("is_scenario_executing not in", values, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingBetween(Byte value1, Byte value2) { + addCriterion("is_scenario_executing between", value1, value2, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsScenarioExecutingNotBetween(Byte value1, Byte value2) { + addCriterion("is_scenario_executing not between", value1, value2, "isScenarioExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingIsNull() { + addCriterion("is_performance_executing is null"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingIsNotNull() { + addCriterion("is_performance_executing is not null"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingEqualTo(Byte value) { + addCriterion("is_performance_executing =", value, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingNotEqualTo(Byte value) { + addCriterion("is_performance_executing <>", value, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingGreaterThan(Byte value) { + addCriterion("is_performance_executing >", value, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingGreaterThanOrEqualTo(Byte value) { + addCriterion("is_performance_executing >=", value, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingLessThan(Byte value) { + addCriterion("is_performance_executing <", value, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingLessThanOrEqualTo(Byte value) { + addCriterion("is_performance_executing <=", value, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingIn(List values) { + addCriterion("is_performance_executing in", values, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingNotIn(List values) { + addCriterion("is_performance_executing not in", values, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingBetween(Byte value1, Byte value2) { + addCriterion("is_performance_executing between", value1, value2, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andIsPerformanceExecutingNotBetween(Byte value1, Byte value2) { + addCriterion("is_performance_executing not between", value1, value2, "isPerformanceExecuting"); + return (Criteria) this; + } + + public Criteria andPrincipalIsNull() { + addCriterion("principal is null"); + return (Criteria) this; + } + + public Criteria andPrincipalIsNotNull() { + addCriterion("principal is not null"); + return (Criteria) this; + } + + public Criteria andPrincipalEqualTo(String value) { + addCriterion("principal =", value, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalNotEqualTo(String value) { + addCriterion("principal <>", value, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalGreaterThan(String value) { + addCriterion("principal >", value, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalGreaterThanOrEqualTo(String value) { + addCriterion("principal >=", value, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalLessThan(String value) { + addCriterion("principal <", value, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalLessThanOrEqualTo(String value) { + addCriterion("principal <=", value, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalLike(String value) { + addCriterion("principal like", value, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalNotLike(String value) { + addCriterion("principal not like", value, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalIn(List values) { + addCriterion("principal in", values, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalNotIn(List values) { + addCriterion("principal not in", values, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalBetween(String value1, String value2) { + addCriterion("principal between", value1, value2, "principal"); + return (Criteria) this; + } + + public Criteria andPrincipalNotBetween(String value1, String value2) { + addCriterion("principal not between", value1, value2, "principal"); + 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); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportDataMapper.java b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportDataMapper.java new file mode 100644 index 0000000000..dc28f050e4 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportDataMapper.java @@ -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 selectByExampleWithBLOBs(TestPlanReportDataExample example); + + List 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); +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportDataMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportDataMapper.xml new file mode 100644 index 0000000000..5302966bd0 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportDataMapper.xml @@ -0,0 +1,312 @@ + + + + + + + + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + id, test_plan_report_id + + + execute_result, failur_test_cases, module_execute_result, api_case_info, scenario_info, + performance_info, issues_info + + + + + + delete from test_plan_report_data + where id = #{id,jdbcType=VARCHAR} + + + delete from test_plan_report_data + + + + + + 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 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, + + + + + #{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}, + + + + + + update test_plan_report_data + + + 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}, + + + + + + + + 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} + + + + + + update test_plan_report_data + set id = #{record.id,jdbcType=VARCHAR}, + test_plan_report_id = #{record.testPlanReportId,jdbcType=VARCHAR} + + + + + + update test_plan_report_data + + + 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 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 test_plan_report_data + set test_plan_report_id = #{testPlanReportId,jdbcType=VARCHAR} + where id = #{id,jdbcType=VARCHAR} + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportMapper.java b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportMapper.java new file mode 100644 index 0000000000..59dbccbdcd --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportMapper.java @@ -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 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); +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportMapper.xml new file mode 100644 index 0000000000..91e407c67a --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/TestPlanReportMapper.xml @@ -0,0 +1,354 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + + + + + + + + and ${criterion.condition} + + + and ${criterion.condition} #{criterion.value} + + + and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} + + + and ${criterion.condition} + + #{listItem} + + + + + + + + + + + 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 + + + + + delete from test_plan_report + where id = #{id,jdbcType=VARCHAR} + + + delete from test_plan_report + + + + + + 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 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, + + + + + #{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}, + + + + + + update test_plan_report + + + 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}, + + + + + + + + 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} + + + + + + update test_plan_report + + + 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 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} + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.java index 8990ca9b8c..361e802c8c 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.java @@ -17,4 +17,6 @@ public interface ExtTestPlanApiCaseMapper { List getIdsByPlanId(String planId); List getNotRelevanceCaseIds(@Param("planId")String planId, @Param("relevanceProjectIds")List relevanceProjectIds); + + List getStatusByTestPlanId(String id); } \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.xml index e7e75b9cc8..bcd364cd3f 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanApiCaseMapper.xml @@ -125,5 +125,8 @@ where t.test_plan_id = #{planId} + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.java index 29bf5bc474..688d4621c2 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.java @@ -9,4 +9,5 @@ public interface ExtTestPlanLoadCaseMapper { List selectIdsNotInPlan(@Param("projectId") String projectId, @Param("planId") String planId); List selectTestPlanLoadCaseList(@Param("planId") String planId, @Param("projectId") String projectId); + void updateCaseStatus(@Param("reportId") String reportId, @Param("status") String status); } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.xml index ace3c621e2..26b0f9147d 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanLoadCaseMapper.xml @@ -1,6 +1,9 @@ + + update test_plan_load_case tplc set status = #{status} where tplc.load_report_id = #{reportId} + + + + + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.java new file mode 100644 index 0000000000..4ce6c330b5 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.java @@ -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 list(@Param("request")QueryTestPlanReportRequest request); +} diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.xml new file mode 100644 index 0000000000..426f7eec36 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtTestPlanReportMapper.xml @@ -0,0 +1,33 @@ + + + + + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/commons/constants/ApiRunMode.java b/backend/src/main/java/io/metersphere/commons/constants/ApiRunMode.java index 5dd7a0e5c3..d160b6908a 100644 --- a/backend/src/main/java/io/metersphere/commons/constants/ApiRunMode.java +++ b/backend/src/main/java/io/metersphere/commons/constants/ApiRunMode.java @@ -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 } diff --git a/backend/src/main/java/io/metersphere/commons/constants/ReportTriggerMode.java b/backend/src/main/java/io/metersphere/commons/constants/ReportTriggerMode.java index 8f9f702d00..af66fc3761 100644 --- a/backend/src/main/java/io/metersphere/commons/constants/ReportTriggerMode.java +++ b/backend/src/main/java/io/metersphere/commons/constants/ReportTriggerMode.java @@ -1,5 +1,11 @@ package io.metersphere.commons.constants; public enum ReportTriggerMode { - MANUAL, SCHEDULE, API + MANUAL, + SCHEDULE, + API, + /** + * 性能测试用例执行触发报告 + */ + CASE } diff --git a/backend/src/main/java/io/metersphere/job/sechedule/TestPlanTestJob.java b/backend/src/main/java/io/metersphere/job/sechedule/TestPlanTestJob.java index 2d4b293867..5a930e0bac 100644 --- a/backend/src/main/java/io/metersphere/job/sechedule/TestPlanTestJob.java +++ b/backend/src/main/java/io/metersphere/job/sechedule/TestPlanTestJob.java @@ -2,46 +2,50 @@ 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.consumer.LoadTestFinishEvent; 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.*; /** * 情景测试Job + * * @author song.tianyang * @Date 2020/12/22 2:59 下午 * @Description */ -public class TestPlanTestJob extends MsScheduleJob { - private String projectID; - private List scenarioIds; - private List apiTestCaseIds; - private List performanceIds; +public class TestPlanTestJob extends MsScheduleJob { + private String projectID; + private Map planScenarioIdMap; + private Map apiTestCaseIdMap; + private Map 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 +53,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 +68,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 testPlanApiScenarioList = testPlanScenarioCaseService.getCasesByPlanId(testPlanID); - for (TestPlanApiScenario model: - testPlanApiScenarioList) { - scenarioIds.add(model.getApiScenarioId()); + planScenarioIdMap = new LinkedHashMap<>(); + apiTestCaseIdMap = new LinkedHashMap<>(); + performanceIdMap = new LinkedHashMap<>(); + + List testPlanApiScenarioList = testPlanScenarioCaseService.getCasesByPlanId(this.resourceId); + for (TestPlanApiScenario model :testPlanApiScenarioList) { + planScenarioIdMap.put(model.getApiScenarioId(),model.getId()); } - List testPlanApiCaseList = testPlanApiCaseService.getCasesByPlanId(testPlanID); + List 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 testPlanLoadCaseDTOList = testPlanLoadCaseService.list(loadCaseRequest); + for (TestPlanLoadCaseDTO dto : testPlanLoadCaseDTOList) { + performanceIdMap.put(dto.getId(),dto.getLoadCaseId()); } businessExecute(context); @@ -85,39 +101,67 @@ 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); //执行接口案例任务 - for (String apiCaseID:apiTestCaseIds) { + for (Map.Entry 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> testPlanScenarioIdMap = new HashMap<>(); + testPlanScenarioIdMap.put(resourceId, this.planScenarioIdMap); + scenarioRequest.setTestPlanScenarioIDMap(testPlanScenarioIdMap); scenarioRequest.setReportUserID(this.userId); - scenarioRequest.setRunMode(ApiRunMode.SCENARIO_PLAN.name()); + scenarioRequest.setTestPlanID(this.resourceId); + scenarioRequest.setRunMode(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name()); + scenarioRequest.setTestPlanReportId(testPlanReport.getId()); String reportID = 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); + //执行性能测试任务 + boolean havePerformanceTask = false; + List performaneReportIDList = new ArrayList<>(); + for (Map.Entry entry: this.performanceIdMap.entrySet()) { + String id = entry.getKey(); + String caseID = entry.getValue(); + RunTestPlanRequest performanceRequest = new RunTestPlanRequest(); + performanceRequest.setId(id); + performanceRequest.setTestPlanLoadId(caseID); + performanceRequest.setTriggerMode(ReportTriggerMode.SCHEDULE.name()); + + String reportId = null; + havePerformanceTask = true; + + try { + reportId = performanceTestService.run(performanceRequest); + }catch (Exception e){ + } + if(reportID!=null){ + TestPlanLoadCase testPlanLoadCase = new TestPlanLoadCase(); + testPlanLoadCase.setId(performanceRequest.getTestPlanLoadId()); + testPlanLoadCase.setLoadReportId(reportId); + testPlanLoadCaseService.update(testPlanLoadCase); + performaneReportIDList.add(reportID); + } + } + + if(!performaneReportIDList.isEmpty()){ + //性能测试时保存性能测试报告ID,在结果返回时用于捕捉并进行 + testPlanReportService.updatePerformanceInfo(testPlanReport,performaneReportIDList); + } + } public static JobKey getJobKey(String testId) { diff --git a/backend/src/main/java/io/metersphere/track/controller/TestPlanReportController.java b/backend/src/main/java/io/metersphere/track/controller/TestPlanReportController.java new file mode 100644 index 0000000000..a0e642af7e --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/controller/TestPlanReportController.java @@ -0,0 +1,55 @@ +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.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(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryTestPlanReportRequest request) { + String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId(); + request.setWorkspaceId(currentWorkspaceId); + Page 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 testPlanReportIdList) { + testPlanReportService.delete(testPlanReportIdList); + } +} diff --git a/backend/src/main/java/io/metersphere/track/dto/TestPlanReportDTO.java b/backend/src/main/java/io/metersphere/track/dto/TestPlanReportDTO.java new file mode 100644 index 0000000000..4db502b2b0 --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/dto/TestPlanReportDTO.java @@ -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 String createTime; + private String triggerMode; + + private TestCaseReportAdvanceStatusResultDTO executeResult; + private List moduleExecuteResult; + private FailureTestCasesAdvanceDTO failureTestCases; + private List Issues; + private List executors; + private String principal; + private Long startTime; + private Long endTime; + private String projectName; +} \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/track/request/report/QueryTestPlanReportRequest.java b/backend/src/main/java/io/metersphere/track/request/report/QueryTestPlanReportRequest.java new file mode 100644 index 0000000000..5ecd4210de --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/request/report/QueryTestPlanReportRequest.java @@ -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 orders; + private Map> filters; +// private Map combine; +} diff --git a/backend/src/main/java/io/metersphere/track/service/LoadReportStatusEvent.java b/backend/src/main/java/io/metersphere/track/service/LoadReportStatusEvent.java new file mode 100644 index 0000000000..62364e0180 --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/service/LoadReportStatusEvent.java @@ -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); + } + } + } +} diff --git a/backend/src/main/java/io/metersphere/track/service/LoadReportStatusTask.java b/backend/src/main/java/io/metersphere/track/service/LoadReportStatusTask.java deleted file mode 100644 index 17a9daab64..0000000000 --- a/backend/src/main/java/io/metersphere/track/service/LoadReportStatusTask.java +++ /dev/null @@ -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); - } -} diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanApiCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanApiCaseService.java index db89c1962e..afdce0e41c 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanApiCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanApiCaseService.java @@ -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 relevanceProjectIds) { TestPlanApiCaseBatchRequest request = new TestPlanApiCaseBatchRequest(); request.setPlanId(planId); diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseEvent.java b/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseEvent.java new file mode 100644 index 0000000000..d2b74158a6 --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseEvent.java @@ -0,0 +1,32 @@ +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.consumer.LoadTestFinishEvent; +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) { + if (StringUtils.equals(NoticeConstants.Mode.SCHEDULE, loadTestReport.getTriggerMode()) ) { + if (StringUtils.equalsAny(loadTestReport.getStatus(), + PerformanceTestStatus.Completed.name(), PerformanceTestStatus.Error.name())) { + testPlanReportService.updatePerformanceTestStatus(loadTestReport.getId()); + } + } + } +} diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseService.java index 3dd1a644d3..58ec34980b 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanLoadCaseService.java @@ -40,8 +40,6 @@ public class TestPlanLoadCaseService { private LoadTestReportMapper loadTestReportMapper; @Resource private LoadTestMapper loadTestMapper; - @Resource - private LoadReportStatusTask loadReportStatusTask; public List relevanceList(LoadCaseRequest request) { List 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; } diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java new file mode 100644 index 0000000000..ddd3586980 --- /dev/null +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanReportService.java @@ -0,0 +1,407 @@ +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.ApiRunMode; +import io.metersphere.commons.constants.NoticeConstants; +import io.metersphere.commons.constants.ReportTriggerMode; +import io.metersphere.commons.constants.TestPlanStatus; +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.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; + + public List list(QueryTestPlanReportRequest request) { + request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); + String projectId = SessionUtils.getCurrentProjectId(); + if (StringUtils.isNotBlank(projectId)) { + request.setProjectId(projectId); + } + List returnList = extTestPlanReportMapper.list(request); + return returnList; + } + + public TestPlanReport genTestPlanReport(String planId, String userId) { + TestPlanReportDTO returnDTO = new TestPlanReportDTO(); + + TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId); + + TestPlanApiCaseExample apiExample = new TestPlanApiCaseExample(); + apiExample.createCriteria().andTestPlanIdEqualTo(planId); + List apiCaseIdList = testPlanApiCaseMapper.selectByExample(apiExample) + .stream().map(TestPlanApiCase::getApiCaseId).collect(Collectors.toList()); + + TestPlanApiScenarioExample example = new TestPlanApiScenarioExample(); + example.createCriteria().andTestPlanIdEqualTo(planId); + List scenarioIdList = testPlanScenarioCaseMapper.selectByExample(example) + .stream().map(TestPlanApiScenario::getApiScenarioId).collect(Collectors.toList()); + + LoadCaseRequest loadCaseRequest = new LoadCaseRequest(); + loadCaseRequest.setTestPlanId(planId); + loadCaseRequest.setProjectId(testPlan.getProjectId()); + List 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(ReportTriggerMode.SCHEDULE.name()); + 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 updateTestPlanReport(String planId) throws Exception { + TestPlanReportDTO returnDTO = new TestPlanReportDTO(); + + QueryTestPlanRequest queryTestPlanRequest = new QueryTestPlanRequest(); + queryTestPlanRequest.setId(planId); + TestPlanDTO testPlan = extTestPlanMapper.list(queryTestPlanRequest).get(0); + + JSONObject content = JSONObject.parseObject("{\"components\":[1,2,3,4,5]}"); + JSONArray componentIds = content.getJSONArray("components"); + + List components = ReportComponentFactory.createComponents(componentIds.toJavaList(String.class), testPlan); + List issues = testPlanService.buildFunctionalCaseReport(planId, components); + testPlanService.buildApiCaseReport(planId, components); + testPlanService.buildScenarioCaseReport(planId, components); + + TestCaseReportMetricDTO testCaseReportMetricDTO = new TestCaseReportMetricDTO(); + components.forEach(component -> { + component.afterBuild(testCaseReportMetricDTO); + }); + + String testPlanReportID = UUID.randomUUID().toString(); + TestPlanReport testPlanReport = new TestPlanReport(); + testPlanReport.setTestPlanId(planId); + testPlanReport.setId(testPlanReportID); + testPlanReport.setCreateTime(System.currentTimeMillis()); + testPlanReport.setUpdateTime(System.currentTimeMillis()); + testPlanReport.setName(testPlan.getName() + "-" + DateUtils.getTimeString(new Date())); + testPlanReport.setStatus("error"); + testPlanReport.setTriggerMode(ReportTriggerMode.MANUAL.name()); + testPlanReport.setCreator(SessionUtils.getUser().getId()); + testPlanReport.setStartTime(System.currentTimeMillis()); + testPlanReport.setEndTime(System.currentTimeMillis()); + testPlanReport.setIsApiCaseExecuting(false); + testPlanReport.setIsScenarioExecuting(false); + testPlanReport.setIsPerformanceExecuting(false); + testPlanReport.setPrincipal(testPlan.getPrincipal()); + + testPlanReportMapper.insert(testPlanReport); + + + TestPlanReportDataWithBLOBs testPlanReportData = new TestPlanReportDataWithBLOBs(); + testPlanReportData.setId(UUID.randomUUID().toString()); + testPlanReportData.setTestPlanReportId(testPlanReportID); + testPlanReportData.setExecuteResult(JSONObject.toJSONString(testCaseReportMetricDTO.getExecuteResult())); + testPlanReportData.setFailurTestCases(JSONObject.toJSONString(testCaseReportMetricDTO.getFailureTestCases())); + testPlanReportData.setModuleExecuteResult(JSONArray.toJSONString(testCaseReportMetricDTO.getModuleExecuteResult())); + + TestPlanApiCaseExample apiExample = new TestPlanApiCaseExample(); + apiExample.createCriteria().andTestPlanIdEqualTo(planId); + List apiCaseIdList = testPlanApiCaseMapper.selectByExample(apiExample) + .stream().map(TestPlanApiCase::getApiCaseId).collect(Collectors.toList()); + + TestPlanApiScenarioExample example = new TestPlanApiScenarioExample(); + example.createCriteria().andTestPlanIdEqualTo(planId); + List scenarioIdList = testPlanScenarioCaseMapper.selectByExample(example) + .stream().map(TestPlanApiScenario::getApiScenarioId).collect(Collectors.toList()); + List performanceIdList = new ArrayList<>(); + testPlanReportData.setApiCaseInfo(JSONArray.toJSONString(apiCaseIdList)); + testPlanReportData.setScenarioInfo(JSONArray.toJSONString(scenarioIdList)); + testPlanReportData.setPerformanceInfo(JSONArray.toJSONString(performanceIdList)); + testPlanReportData.setIssuesInfo(JSONArray.toJSONString(issues)); + + testPlanReportDataMapper.insert(testPlanReportData); + + return returnDTO; + } + +// public TestCaseReport getTestCaseReport(String id) { +// return null; +// } + + 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 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 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 testPlanReportIdList, String runMode) { + planReportForeach: + for (String planReportId : testPlanReportIdList) { + TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(planReportId); + + QueryTestPlanRequest queryTestPlanRequest = new QueryTestPlanRequest(); + queryTestPlanRequest.setId(testPlanReport.getTestPlanId()); + TestPlanDTO testPlan = extTestPlanMapper.list(queryTestPlanRequest).get(0); + + //因为接口案例是单个案例开线程运行, 所以要检查是否都执行完成。全部执行完成时才会进行统一整理 + if (StringUtils.equalsAny(runMode, ApiRunMode.SCHEDULE_API_PLAN.name())) { + List statusList = extTestPlanApiCaseMapper.getStatusByTestPlanId(testPlan.getId()); + for (String status : statusList) { + if (status == null) { + continue planReportForeach; + } + } + } + + testPlanReport.setEndTime(System.currentTimeMillis()); + testPlanReport.setUpdateTime(System.currentTimeMillis()); + + JSONObject content = JSONObject.parseObject("{\"components\":[1,2,3,4,5]}"); + JSONArray componentIds = content.getJSONArray("components"); + List 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(runMode, ApiRunMode.SCHEDULE_API_PLAN.name())) { + testPlanReport.setIsApiCaseExecuting(false); + } else if (StringUtils.equals(runMode, ApiRunMode.SCHEDULE_SCENARIO_PLAN.name())) { + testPlanReport.setIsScenarioExecuting(false); + } else if (StringUtils.equals(runMode, ApiRunMode.SCHEDULE_PERFORMANCE_TEST.name())) { + testPlanReport.setIsPerformanceExecuting(false); + } + TestCaseReportMetricDTO testCaseReportMetricDTO = new TestCaseReportMetricDTO(); + components.forEach(component -> { + component.afterBuild(testCaseReportMetricDTO); + }); + + this.update(testPlanReport); + + TestPlanReportDataExample example = new TestPlanReportDataExample(); + example.createCriteria().andTestPlanReportIdEqualTo(planReportId); + List 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 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 performaneReportIDList) { + TestPlanReportDataExample example = new TestPlanReportDataExample(); + example.createCriteria().andTestPlanReportIdEqualTo(testPlanReport.getId()); + List reportDataList = testPlanReportDataMapper.selectByExampleWithBLOBs(example); + for (TestPlanReportDataWithBLOBs models : reportDataList) { + models.setPerformanceInfo(JSONArray.toJSONString(performaneReportIDList)); + testPlanReportDataMapper.updateByPrimaryKeyWithBLOBs(models); + } + } + + public void updatePerformanceTestStatus(String reportId) { + List testPlanReportId = extTestPlanMapper.findIdByPerformanceReportId(reportId); + this.updateReport(testPlanReportId, ApiRunMode.SCHEDULE_PERFORMANCE_TEST.name()); + } + + public void delete(List testPlanReportIdList) { + for (String testPlanReportId : testPlanReportIdList) { + testPlanReportMapper.deleteByPrimaryKey(testPlanReportId); + TestPlanReportDataExample example = new TestPlanReportDataExample(); + example.createCriteria().andTestPlanReportIdEqualTo(testPlanReportId); + testPlanReportDataMapper.deleteByExample(example); + } + } +} diff --git a/backend/src/main/java/io/metersphere/track/service/TestPlanService.java b/backend/src/main/java/io/metersphere/track/service/TestPlanService.java index d9c6519a1e..105a85b727 100644 --- a/backend/src/main/java/io/metersphere/track/service/TestPlanService.java +++ b/backend/src/main/java/io/metersphere/track/service/TestPlanService.java @@ -720,4 +720,12 @@ public class TestPlanService { public List 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); + } } diff --git a/backend/src/main/resources/db/migration/V66__init_test_plan_report.sql b/backend/src/main/resources/db/migration/V66__init_test_plan_report.sql new file mode 100644 index 0000000000..576f2df200 --- /dev/null +++ b/backend/src/main/resources/db/migration/V66__init_test_plan_report.sql @@ -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; \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index a0f2d44465..10bf93c1b4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -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", diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index 6763fe9b5b..da0d8a805c 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -458,6 +458,7 @@ // 直接更新场景防止编辑内容丢失 this.editScenario(); } + this.reload(); }, showButton(...names) { for (const name of names) { @@ -521,8 +522,9 @@ this.$refs.apiImport.open(); break; } - - this.selectedNode.expanded = true; + if (this.selectedNode) { + this.selectedNode.expanded = true; + } this.sort(); }, nodeClick(data, node) { diff --git a/frontend/src/business/components/api/automation/scenario/LoopController.vue b/frontend/src/business/components/api/automation/scenario/LoopController.vue index c6b2864741..79f126c779 100644 --- a/frontend/src/business/components/api/automation/scenario/LoopController.vue +++ b/frontend/src/business/components/api/automation/scenario/LoopController.vue @@ -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')"> -
diff --git a/frontend/src/business/components/common/components/search/search-components.js b/frontend/src/business/components/common/components/search/search-components.js index 932a434f85..8dec5ba03d 100644 --- a/frontend/src/business/components/common/components/search/search-components.js +++ b/frontend/src/business/components/common/components/search/search-components.js @@ -88,6 +88,14 @@ export const TEST_NAME = { options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE] }, } +export const TEST_PLAN_NAME = { + key: "testPlanName", + name: 'MsTableSearchInput', + label: 'test_track.report.list.test_plan', + operator: { + options: [OPERATORS.LIKE, OPERATORS.NOT_LIKE] + }, +} export const CREATE_TIME = { key: "createTime", name: 'MsTableSearchDateTimePicker', @@ -406,6 +414,22 @@ export const TEST_PLAN_STATUS = { } }; +export const TEST_PLAN_TRIGGER_MODE = { + key: "triggerMode", + name: 'MsTableSearchSelect', + label: "test_track.report.list.trigger_mode", + operator: { + options: [OPERATORS.IN, OPERATORS.NOT_IN] + }, + options: [ + {label: 'test_track.report.trigger_mode.manual', value: 'manual'}, + {label: 'test_track.report.trigger_mode.automation', value: 'automation'}, + ], + props: { + multiple: true + } +}; + export const TEST_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, STATUS, CREATOR]; export const REPORT_CONFIGS = [NAME, TEST_NAME, CREATE_TIME, STATUS, CREATOR, TRIGGER_MODE]; @@ -417,3 +441,5 @@ export const TEST_PLAN_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, PRINCIPAL, TES export const API_DEFINITION_CONFIGS = [NAME, API_METHOD, API_PATH, API_STATUS, API_TAGS, UPDATE_TIME, CREATE_TIME, CREATOR]; export const API_CASE_CONFIGS = [NAME, API_CASE_PRIORITY, API_TAGS, API_CASE_RESULT, UPDATE_TIME, CREATE_TIME, CREATOR]; + +export const TEST_PLAN_REPORT_CONFIGS = [NAME, TEST_PLAN_NAME,CREATOR, CREATE_TIME, TEST_PLAN_TRIGGER_MODE, TEST_PLAN_STATUS]; diff --git a/frontend/src/business/components/common/json-schema/schema/editor/main.vue b/frontend/src/business/components/common/json-schema/schema/editor/main.vue index 4c32a04035..ce1814d34d 100644 --- a/frontend/src/business/components/common/json-schema/schema/editor/main.vue +++ b/frontend/src/business/components/common/json-schema/schema/editor/main.vue @@ -1,32 +1,32 @@ + + + + diff --git a/frontend/src/business/components/track/report/components/TestPlanReportView.vue b/frontend/src/business/components/track/report/components/TestPlanReportView.vue new file mode 100644 index 0000000000..6d9e2a1a33 --- /dev/null +++ b/frontend/src/business/components/track/report/components/TestPlanReportView.vue @@ -0,0 +1,266 @@ + + +cd + + diff --git a/frontend/src/business/components/track/router.js b/frontend/src/business/components/track/router.js index 01cc002207..db1f16232d 100644 --- a/frontend/src/business/components/track/router.js +++ b/frontend/src/business/components/track/router.js @@ -6,6 +6,8 @@ const TestPlan = () => import('@/business/components/track/plan/TestPlan') const TestCaseReview = () => import('@/business/components/track/review/TestCaseReview') const TestCaseReviewView = () => import('@/business/components/track/review/view/TestCaseReviewView') const TestPlanView = () => import('@/business/components/track/plan/view/TestPlanView') +const reportListView = () => import('@/business/components/track/report/TestPlanReport') +// const reportListView = () => import('@/business/components/track/plan/TestPlan') export default { path: "/track", @@ -35,6 +37,11 @@ export default { name: 'testCaseEdit', component: TestCase, }, + { + path: 'testPlan/reportList', + name: 'testPlanReportList', + component: reportListView, + }, { path: "plan/:type", name: "testPlan", diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 0a040ccbdc..ace4e4e19a 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -1252,6 +1252,22 @@ export default { tapd_current_owner: "Tapd Current Owner:", zentao_bug_build: "Zentao bug Impact version", zentao_bug_assigned: "Zentao bug handler", + }, + report: { + name: "Test Plan Report", + list: { + name: "name", + test_plan: "Test plan", + creator: "Creator", + create_time: "Create Time", + trigger_mode: "Trigger Mode", + status: "Status", + operation: "Operation", + }, + trigger_mode: { + manual: "Manual", + automation: "Automation", + }, } }, test_resource_pool: { diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index f507566fde..2ec75b7ddd 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -1253,6 +1253,22 @@ export default { tapd_current_owner: "Tapd bug 处理人:", zentao_bug_build: "禅道 bug 影响版本", zentao_bug_assigned: "禅道 bug 处理人", + }, + report: { + name: "测试计划报告", + list: { + name: "名称", + test_plan: "测试计划名称", + creator: "创建人", + create_time: "创建时间", + trigger_mode: "触发方式", + status: "状态", + operation: "操作", + }, + trigger_mode: { + manual: "手动触发", + automation: "自动触发", + }, } }, test_resource_pool: { diff --git a/frontend/src/i18n/zh-TW.js b/frontend/src/i18n/zh-TW.js index 551d04bc7e..f3040e1377 100644 --- a/frontend/src/i18n/zh-TW.js +++ b/frontend/src/i18n/zh-TW.js @@ -1253,6 +1253,22 @@ export default { tapd_current_owner: "Tapd bug 處理人:", zentao_bug_build: "禪道 bug 影響版本", zentao_bug_assigned: "禪道 bug 處理人", + }, + report: { + name: "測試計畫包括", + list: { + name: "名稱", + test_plan: "測試計畫名稱", + creator: "創建人", + create_time: "創建時間", + trigger_mode: "觸發方式", + status: "狀態", + operation: "操作", + }, + trigger_mode: { + manual: "手動觸發", + automation: "自動觸發", + }, } }, test_resource_pool: { diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..48e341a095 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3 @@ +{ + "lockfileVersion": 1 +}