From c291de32923e5323be6790457112595071da9fd8 Mon Sep 17 00:00:00 2001 From: fit2-zhao Date: Fri, 8 Jan 2021 13:29:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E6=8E=A5=E5=8F=A3=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96):=20=E5=9C=BA=E6=99=AF=E5=8F=98=E9=87=8F=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAutomationController.java | 31 ++++------ .../dto/definition/request/MsScenario.java | 22 ++++--- .../request/variable/ScenarioVariable.java | 29 +++++++++ .../api/service/ApiAutomationService.java | 45 +++++++++----- .../api/service/ApiDefinitionService.java | 7 +-- .../service/HistoricalDataUpgradeService.java | 2 +- frontend/package.json | 1 + .../automation/scenario/EditApiScenario.vue | 18 +++++- .../automation/scenario/variable/EditCsv.vue | 61 +++++++++++++++++-- .../scenario/variable/VariableList.vue | 2 +- frontend/src/business/main.js | 2 + 11 files changed, 168 insertions(+), 52 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/api/dto/definition/request/variable/ScenarioVariable.java 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 464eb869fb..f739b7de51 100644 --- a/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java +++ b/backend/src/main/java/io/metersphere/api/controller/ApiAutomationController.java @@ -5,37 +5,26 @@ import com.github.pagehelper.PageHelper; import io.metersphere.api.dto.JmxInfoDTO; import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.definition.RunDefinitionRequest; -import io.metersphere.api.dto.definition.request.*; -import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.service.ApiAutomationService; import io.metersphere.base.domain.ApiScenario; import io.metersphere.base.domain.ApiScenarioWithBLOBs; import io.metersphere.base.domain.Schedule; -import io.metersphere.commons.constants.ReportTriggerMode; import io.metersphere.commons.constants.RoleConstants; -import io.metersphere.commons.exception.MSException; -import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.SessionUtils; -import io.metersphere.i18n.Translator; -import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; -import io.metersphere.track.request.testplan.SaveTestPlanRequest; -import org.apache.commons.lang3.StringUtils; -import org.apache.jmeter.save.SaveService; -import org.apache.jorphan.collections.HashTree; -import org.apache.jorphan.collections.ListedHashTree; +import io.metersphere.track.request.testplan.FileOperationRequest; import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresRoles; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.io.ByteArrayOutputStream; -import java.util.LinkedList; import java.util.List; -import java.util.UUID; @RestController @RequestMapping(value = "/api/automation") @@ -44,9 +33,6 @@ public class ApiAutomationController { @Resource ApiAutomationService apiAutomationService; - @Resource - PerformanceTestService performanceTestService; - @PostMapping("/list/{goPage}/{pageSize}") @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR) @@ -145,5 +131,14 @@ public class ApiAutomationController { runRequest.setExecuteType(ExecuteType.Completed.name()); return apiAutomationService.genPerformanceTestJmx(runRequest); } + + @PostMapping("/file/download") + public ResponseEntity downloadJmx(@RequestBody FileOperationRequest fileOperationRequest) { + byte[] bytes = apiAutomationService.loadFileAsBytes(fileOperationRequest); + return ResponseEntity.ok() + .contentType(MediaType.parseMediaType("application/octet-stream")) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileOperationRequest.getName() + "\"") + .body(bytes); + } } diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java index 19097a14bf..c04dc5ecbf 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/MsScenario.java @@ -7,6 +7,7 @@ import com.alibaba.fastjson.annotation.JSONType; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import io.metersphere.api.dto.definition.request.variable.ScenarioVariable; import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.service.ApiAutomationService; @@ -42,7 +43,7 @@ public class MsScenario extends MsTestElement { private String environmentId; @JSONField(ordinal = 23) - private List variables; + private List variables; @JSONField(ordinal = 24) private boolean enableCookieShare; @@ -60,7 +61,7 @@ public class MsScenario extends MsTestElement { } } if (CollectionUtils.isNotEmpty(this.getVariables())) { - config.setVariables(this.variables); + //config.setVariables(this.variables); } if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) { return; @@ -92,17 +93,24 @@ public class MsScenario extends MsTestElement { } } + public void setOldVariables(List oldVariables) { + if (CollectionUtils.isNotEmpty(oldVariables)) { + String json = JSON.toJSONString(oldVariables); + this.variables = JSON.parseArray(json, ScenarioVariable.class); + } + } + private Arguments arguments(ParameterConfig config) { Arguments arguments = new Arguments(); arguments.setEnabled(true); arguments.setName(name + "Variables"); arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel")); - if (CollectionUtils.isNotEmpty(this.getVariables())) { - variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> - arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") - ); - } +// if (CollectionUtils.isNotEmpty(this.getVariables())) { +// variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> +// arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") +// ); +// } if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null && CollectionUtils.isNotEmpty(config.getConfig().getCommonConfig().getVariables())) { config.getConfig().getCommonConfig().getVariables().stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/request/variable/ScenarioVariable.java b/backend/src/main/java/io/metersphere/api/dto/definition/request/variable/ScenarioVariable.java new file mode 100644 index 0000000000..7447f3cf0e --- /dev/null +++ b/backend/src/main/java/io/metersphere/api/dto/definition/request/variable/ScenarioVariable.java @@ -0,0 +1,29 @@ +package io.metersphere.api.dto.definition.request.variable; + +import io.metersphere.api.dto.scenario.request.BodyFile; +import lombok.Data; + +import java.util.List; + +@Data +public class ScenarioVariable { + + // CONSTANT LIST CSV COUNTER RANDOM + private String type; + private String name; + // 常量值,列表值[] ,计数器输出格式,随机数输出格式 + private String value; + private String description; + // csv + private List files; + private String splits; + private String encoding; + // counter + private int startNumber; + private int endNumber; + private int increment; + // random + private int minNumber; + private int maxNumber; + +} 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 f45a8d38ba..7aab0f9c7b 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -11,7 +11,7 @@ import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.request.*; -import io.metersphere.api.dto.scenario.KeyValue; +import io.metersphere.api.dto.definition.request.variable.ScenarioVariable; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.jmeter.JMeterService; import io.metersphere.base.domain.*; @@ -30,18 +30,16 @@ import io.metersphere.commons.utils.ServiceUtils; import io.metersphere.commons.utils.SessionUtils; import io.metersphere.i18n.Translator; import io.metersphere.job.sechedule.ApiScenarioTestJob; -import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.service.ScheduleService; import io.metersphere.track.dto.TestPlanDTO; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest; -import io.metersphere.track.request.testplan.SaveTestPlanRequest; +import io.metersphere.track.request.testplan.FileOperationRequest; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; -import org.apache.jmeter.save.SaveService; import org.apache.jorphan.collections.HashTree; import org.apache.jorphan.collections.ListedHashTree; import org.springframework.stereotype.Service; @@ -50,6 +48,8 @@ import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; import java.util.*; import java.util.stream.Collectors; @@ -78,15 +78,13 @@ public class ApiAutomationService { SqlSessionFactory sqlSessionFactory; @Resource private ApiScenarioReportMapper apiScenarioReportMapper; - @Resource - private PerformanceTestService performanceTestService; public List list(ApiScenarioRequest request) { request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); - if(request.isSelectThisWeedData()){ + if (request.isSelectThisWeedData()) { Map weekFirstTimeAndLastTime = DateUtils.getWeedFirstTimeAndLastTime(new Date()); Date weekFirstTime = weekFirstTimeAndLastTime.get("firstTime"); - if(weekFirstTime!=null){ + if (weekFirstTime != null) { request.setCreateTime(weekFirstTime.getTime()); } } @@ -285,6 +283,22 @@ public class ApiAutomationService { return new ArrayList<>(); } + public byte[] loadFileAsBytes(FileOperationRequest fileOperationRequest) { + File file = new File("/opt/metersphere/data/body/" + fileOperationRequest.getId() + "_" + fileOperationRequest.getName()); + try (FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);) { + byte[] b = new byte[1000]; + int n; + while ((n = fis.read(b)) != -1) { + bos.write(b, 0, n); + } + return bos.toByteArray(); + } catch (Exception ex) { + LogUtil.error(ex.getMessage()); + } + return null; + } + private void createScenarioReport(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID) { APIScenarioReportResult report = new APIScenarioReportResult(); report.setId(id); @@ -354,12 +368,14 @@ public class ApiAutomationService { // 多态JSON普通转换会丢失内容,需要通过 ObjectMapper 获取 if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) { LinkedList elements = mapper.readValue(element.getString("hashTree"), - new TypeReference>() {}); + new TypeReference>() { + }); scenario.setHashTree(elements); } if (StringUtils.isNotEmpty(element.getString("variables"))) { - LinkedList variables = mapper.readValue(element.getString("variables"), - new TypeReference>() {}); + LinkedList variables = mapper.readValue(element.getString("variables"), + new TypeReference>() { + }); scenario.setVariables(variables); } group.setEnableCookieShare(scenario.isEnableCookieShare()); @@ -592,8 +608,8 @@ public class ApiAutomationService { scenario.setHashTree(elements); } if (StringUtils.isNotEmpty(element.getString("variables"))) { - LinkedList variables = mapper.readValue(element.getString("variables"), - new TypeReference>() { + LinkedList variables = mapper.readValue(element.getString("variables"), + new TypeReference>() { }); scenario.setVariables(variables); } @@ -602,7 +618,6 @@ public class ApiAutomationService { scenarios.add(scenario); group.setHashTree(scenarios); testPlan.getHashTree().add(group); - } } catch (Exception ex) { MSException.throwException(ex.getMessage()); @@ -615,6 +630,6 @@ public class ApiAutomationService { JmxInfoDTO dto = new JmxInfoDTO(); dto.setName(name); dto.setXml(jmx); - return dto; + return dto; } } 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 247da9e765..09bd985273 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiDefinitionService.java @@ -13,7 +13,7 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.request.*; -import io.metersphere.api.dto.scenario.KeyValue; +import io.metersphere.api.dto.definition.request.variable.ScenarioVariable; import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.TestResult; @@ -29,7 +29,6 @@ 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; @@ -366,8 +365,8 @@ public class ApiDefinitionService { scenario.setHashTree(elements); } if (StringUtils.isNotEmpty(element.getString("variables"))) { - LinkedList variables = mapper.readValue(element.getString("variables"), - new TypeReference>() {}); + LinkedList variables = mapper.readValue(element.getString("variables"), + new TypeReference>() {}); scenario.setVariables(variables); } group.setEnableCookieShare(scenario.isEnableCookieShare()); diff --git a/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java index f9b028c29a..1b0e36675b 100644 --- a/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java +++ b/backend/src/main/java/io/metersphere/api/service/HistoricalDataUpgradeService.java @@ -66,7 +66,7 @@ public class HistoricalDataUpgradeService { private MsScenario createScenario(Scenario oldScenario) { MsScenario scenario = new MsScenario(); - scenario.setVariables(oldScenario.getVariables()); + scenario.setOldVariables(oldScenario.getVariables()); scenario.setName(oldScenario.getName()); scenario.setEnableCookieShare(oldScenario.isEnableCookieShare()); scenario.setEnvironmentId(oldScenario.getEnvironmentId()); diff --git a/frontend/package.json b/frontend/package.json index 181b934e95..7d7d671066 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -39,6 +39,7 @@ "vue-float-action-button": "^0.6.6", "vue-i18n": "^8.15.3", "vue-input-tag": "^2.0.7", + "vue-papa-parse": "^2.0.0", "vue-pdf": "^4.2.0", "vue-router": "^3.1.3", "vuedraggable": "^2.23.2", diff --git a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue index 9ffd26fd3d..fd5ab5369b 100644 --- a/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue +++ b/frontend/src/business/components/api/automation/scenario/EditApiScenario.vue @@ -803,6 +803,22 @@ this.recursiveFile(item.hashTree, bodyUploadFiles, obj); } }) + // 场景变量csv 文件 + this.currentScenario.variables.forEach(param => { + if (param.type === 'CSV' && param.files) { + param.files.forEach(item => { + if (item.file) { + if (!item.id) { + let fileId = getUUID().substring(0, 12); + item.name = item.file.name; + item.id = fileId; + } + obj.bodyUploadIds.push(item.id); + bodyUploadFiles.push(item.file); + } + }) + } + }) return bodyUploadFiles; }, editScenario() { @@ -842,7 +858,7 @@ // 兼容历史数据 if (item.name) { if (!item.type) { - item.type = "VARIABLE"; + item.type = "CONSTANT"; item.id = getUUID(); } item.num = index; diff --git a/frontend/src/business/components/api/automation/scenario/variable/EditCsv.vue b/frontend/src/business/components/api/automation/scenario/variable/EditCsv.vue index 5a755b76d2..b56d068aa9 100644 --- a/frontend/src/business/components/api/automation/scenario/variable/EditCsv.vue +++ b/frontend/src/business/components/api/automation/scenario/variable/EditCsv.vue @@ -21,7 +21,7 @@ 添加文件 - + @@ -42,7 +42,21 @@ - 配置管理 + + + + + + + + +