diff --git a/backend/src/main/java/io/metersphere/api/controller/APITestController.java b/backend/src/main/java/io/metersphere/api/controller/APITestController.java index 85b1bc768c..883f90772c 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APITestController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APITestController.java @@ -10,16 +10,11 @@ import io.metersphere.api.dto.datacount.response.ApiDataCountDTO; import io.metersphere.api.dto.datacount.response.ExecutedCaseInfoDTO; import io.metersphere.api.dto.datacount.response.TaskInfoResult; import io.metersphere.api.dto.definition.RunDefinitionRequest; -import io.metersphere.api.dto.definition.request.MsTestElement; import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter; import io.metersphere.api.service.*; -import io.metersphere.base.domain.ApiDefinition; import io.metersphere.base.domain.ApiTest; -import io.metersphere.base.domain.LoadTest; import io.metersphere.base.domain.Schedule; -import io.metersphere.commons.constants.PerformanceTestStatus; import io.metersphere.commons.constants.RoleConstants; -import io.metersphere.commons.constants.ScheduleGroup; import io.metersphere.commons.utils.CronUtils; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; @@ -28,24 +23,14 @@ import io.metersphere.controller.request.QueryScheduleRequest; import io.metersphere.dto.ScheduleDao; import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.service.CheckPermissionService; -import io.metersphere.service.FileService; import io.metersphere.service.ScheduleService; -import io.metersphere.track.request.testplan.SaveTestPlanRequest; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.entity.ContentType; import org.apache.jorphan.collections.HashTree; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.io.ByteArrayInputStream; -import java.io.InputStream; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Date; diff --git a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java index 52c7ac385e..db9e688e93 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -160,5 +160,11 @@ public class ApiAutomationController { return apiAutomationService.export(request); } + @PostMapping(value = "/export/jmx") + @RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR) + public List exportJmx(@RequestBody ApiScenarioBatchRequest request) { + return apiAutomationService.exportJmx(request); + } + } diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenrioExportJmx.java b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenrioExportJmx.java new file mode 100644 index 0000000000..bd42d877bc --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenrioExportJmx.java @@ -0,0 +1,16 @@ +package io.metersphere.api.dto.automation; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ApiScenrioExportJmx { + private String name; + private String jmx; + + public ApiScenrioExportJmx(String name, String jmx) { + this.name = name; + this.jmx = jmx; + } +} diff --git a/backend/src/main/java/io/metersphere/api/dto/automation/parse/MsJmeterParser.java b/backend/src/main/java/io/metersphere/api/dto/automation/parse/MsJmeterParser.java index 067a2478d2..95073d5b45 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/parse/MsJmeterParser.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/parse/MsJmeterParser.java @@ -88,7 +88,7 @@ public class MsJmeterParser extends ScenarioImportAbstractParser { preInitPool(request.getProjectId(), testPlan); MsScenario scenario = new MsScenario(); - scenario.setReferenced("REF"); + scenario.setReferenced("IMPORT"); jmterHashTree(testPlan, scenario); this.projectId = request.getProjectId(); ScenarioImport scenarioImport = new ScenarioImport(); @@ -233,24 +233,24 @@ public class MsJmeterParser extends ScenarioImportAbstractParser { elementNode.setConsumerAndService(consumerAndService); List methodArguments = Constants.getMethodArgs(sampler); + List methodArgs = new LinkedList<>(); if (CollectionUtils.isNotEmpty(methodArguments)) { - List methodArgs = new LinkedList<>(); methodArguments.forEach(item -> { KeyValue keyValue = new KeyValue(item.getParamType(), item.getParamValue()); methodArgs.add(keyValue); }); - elementNode.setArgs(methodArgs); } + elementNode.setArgs(methodArgs); List arguments = Constants.getAttachmentArgs(sampler); + List attachmentArgs = new LinkedList<>(); if (CollectionUtils.isNotEmpty(arguments)) { - List methodArgs = new LinkedList<>(); arguments.forEach(item -> { KeyValue keyValue = new KeyValue(item.getParamType(), item.getParamValue()); - methodArgs.add(keyValue); + attachmentArgs.add(keyValue); }); - elementNode.setAttachmentArgs(methodArgs); } + elementNode.setAttachmentArgs(attachmentArgs); } /** diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java index fc98f55213..28368aa8ee 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsTestElement.java @@ -164,9 +164,9 @@ public abstract class MsTestElement { } public Arguments addArguments(ParameterConfig config) { - Arguments arguments = new Arguments(); if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null && CollectionUtils.isNotEmpty(config.getConfig().getCommonConfig().getVariables())) { + Arguments arguments = new Arguments(); arguments.setEnabled(true); arguments.setName(name + "Variables"); arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); @@ -174,8 +174,9 @@ public abstract class MsTestElement { config.getConfig().getCommonConfig().getVariables().stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") ); + return arguments; } - return arguments; + return null; } protected EnvironmentConfig getEnvironmentConfig(String environmentId) { diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java index dcd0bb5f19..8cc2ed852e 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/sampler/MsJDBCSampler.java @@ -95,17 +95,18 @@ public class MsJDBCSampler extends MsTestElement { } private Arguments arguments(String name, List variables) { - Arguments arguments = new Arguments(); if (CollectionUtils.isNotEmpty(variables)) { + Arguments arguments = new Arguments(); arguments.setEnabled(true); - arguments.setName(name); + arguments.setName(name + "JDBC_Argument"); arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel")); variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") ); + return arguments; } - return arguments; + return null; } private JDBCSampler jdbcSampler(ParameterConfig config) { 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 2fa83ae36e..444b309f3e 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -435,6 +435,47 @@ public class ApiAutomationService { return jmeterHashTree; } + private String generateJmx(ApiScenarioWithBLOBs apiScenario) { + HashTree jmeterHashTree = new ListedHashTree(); + MsTestPlan testPlan = new MsTestPlan(); + testPlan.setHashTree(new LinkedList<>()); + try { + MsThreadGroup group = new MsThreadGroup(); + group.setLabel(apiScenario.getName()); + group.setName(apiScenario.getName()); + + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + JSONObject element = JSON.parseObject(apiScenario.getScenarioDefinition()); + MsScenario scenario = JSONObject.parseObject(apiScenario.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()); + group.setHashTree(new LinkedList() {{ + this.add(scenario); + }}); + + testPlan.getHashTree().add(group); + } catch (Exception ex) { + MSException.throwException(ex.getMessage()); + } + + testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig()); + return testPlan.getJmx(jmeterHashTree); + } + /** * 场景测试执行 * @@ -515,7 +556,6 @@ public class ApiAutomationService { ParameterConfig config = new ParameterConfig(); config.setConfig(envConfig); HashTree hashTree = request.getTestElement().generateHashTree(config); - System.out.println(request.getTestElement().getJmx(hashTree)); // 调用执行方法 createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(), SessionUtils.getUserId()); @@ -668,7 +708,7 @@ public class ApiAutomationService { HashTree jmeterHashTree = generateHashTree(apiScenarios, request, null); String jmx = testPlan.getJmx(jmeterHashTree); - jmx = apiTestService.updateJmxString(jmx,testName,true); + jmx = apiTestService.updateJmxString(jmx, testName, true); //将ThreadGroup的testname改为接口名称 // Document doc = DocumentHelper.parseText(jmx);// 获取可续保保单列表报文模板 @@ -805,16 +845,32 @@ public class ApiAutomationService { return apiImport; } - public ApiScenrioExportResult export(ApiScenarioBatchRequest request) { + private List getExportResult(ApiScenarioBatchRequest request) { ServiceUtils.getSelectAllIds(request, request.getCondition(), (query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query)); ApiScenarioExample example = new ApiScenarioExample(); example.createCriteria().andIdIn(request.getIds()); List apiScenarioWithBLOBs = apiScenarioMapper.selectByExampleWithBLOBs(example); - ApiScenrioExportResult result = new ApiScenrioExportResult(); - result.setData(apiScenarioWithBLOBs); + return apiScenarioWithBLOBs; + } + + public ApiScenrioExportResult export(ApiScenarioBatchRequest request) { + ApiScenrioExportResult result = new ApiScenrioExportResult(); + result.setData(getExportResult(request)); result.setProjectId(request.getProjectId()); result.setVersion(System.getenv("MS_VERSION")); return result; } + + public List exportJmx(ApiScenarioBatchRequest request) { + List apiScenarioWithBLOBs = getExportResult(request); + // 生成jmx + List resList = new ArrayList<>(); + apiScenarioWithBLOBs.forEach(item -> { + ApiScenrioExportJmx scenrioExportJmx = new ApiScenrioExportJmx(item.getName(), apiTestService.updateJmxString(generateJmx(item), item.getName(), true)); + resList.add(scenrioExportJmx); + }); + return resList; + } + } diff --git a/backend/src/main/java/io/metersphere/xpack b/backend/src/main/java/io/metersphere/xpack index 44bcc98930..b9042074b7 160000 --- a/backend/src/main/java/io/metersphere/xpack +++ b/backend/src/main/java/io/metersphere/xpack @@ -1 +1 @@ -Subproject commit 44bcc9893033900f95c99068cd4edec740465dfe +Subproject commit b9042074b780205e275c674f64417799110519fd diff --git a/frontend/src/business/components/api/automation/ApiAutomation.vue b/frontend/src/business/components/api/automation/ApiAutomation.vue index 44ee0dafdc..2979c5140c 100644 --- a/frontend/src/business/components/api/automation/ApiAutomation.vue +++ b/frontend/src/business/components/api/automation/ApiAutomation.vue @@ -9,6 +9,7 @@ @setNodeTree="setNodeTree" @enableTrash="enableTrash" @exportAPI="exportAPI" + @exportJmx="exportJmx" @refreshAll="refreshAll" :type="'edit'" ref="nodeTree"/> @@ -69,7 +70,6 @@ import MsApiScenarioModule from "@/business/components/api/automation/scenario/ApiScenarioModule"; import MsEditApiScenario from "./scenario/EditApiScenario"; import {getCurrentProjectID} from "../../../../common/js/utils"; - import {PROJECT_NAME} from "../../../../common/js/constants"; export default { name: "ApiAutomation", @@ -133,6 +133,9 @@ exportAPI() { this.$refs.apiScenarioList.exportApi(); }, + exportJmx(){ + this.$refs.apiScenarioList.exportJmx(); + }, checkRedirectEditPage(redirectParam) { if (redirectParam != null) { let selectParamArr = redirectParam.split("edit:"); diff --git a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue index 317795503a..5561ad19cd 100644 --- a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue +++ b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue @@ -167,50 +167,50 @@