From 4f17a1dd58459d966ba41de883d06e96148147f8 Mon Sep 17 00:00:00 2001 From: chenjianxing Date: Mon, 26 Jul 2021 15:06:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E3=80=81=E6=89=B9=E9=87=8F=E5=9C=BA=E6=99=AF=E8=BD=AC=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E6=B5=8B=E8=AF=95=E4=B8=80=E9=94=AE=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/APITestController.java | 24 +- .../io/metersphere/api/dto/JmxInfoDTO.java | 1 + .../dto/automation/ApiScenrioExportJmx.java | 1 + .../definition/SaveApiTestCaseRequest.java | 25 +- .../io/metersphere/api/dto/scenario/Body.java | 4 + .../api/service/APITestService.java | 30 +- .../api/service/ApiAutomationService.java | 1 + .../api/service/ApiTestCaseService.java | 57 ++ .../metersphere/base/domain/ApiLoadTest.java | 21 + .../base/domain/ApiLoadTestExample.java | 610 ++++++++++++++++++ .../metersphere/base/domain/ApiTestCase.java | 4 +- .../base/domain/ApiTestCaseExample.java | 62 +- .../base/domain/TestPlanTestCase.java | 6 +- .../base/domain/TestPlanTestCaseExample.java | 142 ++-- .../base/mapper/ApiLoadTestMapper.java | 30 + .../base/mapper/ApiLoadTestMapper.xml | 228 +++++++ .../base/mapper/ApiTestCaseMapper.xml | 59 +- .../base/mapper/TestPlanTestCaseMapper.xml | 56 +- .../base/mapper/ext/ExtApiLoadTestMapper.java | 8 + .../base/mapper/ext/ExtApiLoadTestMapper.xml | 19 + .../commons/constants/ApiLoadType.java | 5 + .../metersphere/commons/utils/FileUtils.java | 5 + .../listener/AppStartListener.java | 10 + .../controller/PerformanceTestController.java | 2 +- .../request/SaveTestPlanRequest.java | 2 + .../performance/request/TestPlanRequest.java | 4 - .../service/PerformanceTestService.java | 136 ++-- .../service/ApiPerformanceService.java | 59 ++ .../db/migration/V92__v1.11.2_release.sql | 18 +- .../automation/scenario/ApiScenarioList.vue | 1 + .../components/list/ApiCaseSimpleList.vue | 2 + .../components/reference/ApiExtendBtns.vue | 4 +- .../performance/test/EditPerformanceTest.vue | 26 +- 33 files changed, 1440 insertions(+), 222 deletions(-) create mode 100644 backend/src/main/java/io/metersphere/base/domain/ApiLoadTest.java create mode 100644 backend/src/main/java/io/metersphere/base/domain/ApiLoadTestExample.java create mode 100644 backend/src/main/java/io/metersphere/base/mapper/ApiLoadTestMapper.java create mode 100644 backend/src/main/java/io/metersphere/base/mapper/ApiLoadTestMapper.xml create mode 100644 backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiLoadTestMapper.java create mode 100644 backend/src/main/java/io/metersphere/base/mapper/ext/ExtApiLoadTestMapper.xml create mode 100644 backend/src/main/java/io/metersphere/commons/constants/ApiLoadType.java create mode 100644 backend/src/main/java/io/metersphere/service/ApiPerformanceService.java 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 bea9fbe084..0ad23590a0 100644 --- a/backend/src/main/java/io/metersphere/api/controller/APITestController.java +++ b/backend/src/main/java/io/metersphere/api/controller/APITestController.java @@ -58,8 +58,6 @@ public class APITestController { private ScheduleService scheduleService; @Resource private HistoricalDataUpgradeService historicalDataUpgradeService; - @Resource - private ApiTestEnvironmentService environmentService; @GetMapping("recent/{count}") public List recentTest(@PathVariable int count) { @@ -373,27 +371,7 @@ public class APITestController { @PostMapping(value = "/genPerformanceTestXml", consumes = {"multipart/form-data"}) public JmxInfoDTO genPerformanceTest(@RequestPart("request") RunDefinitionRequest runRequest, @RequestPart(value = "files", required = false) List bodyFiles) throws Exception { - - ParameterConfig config = new ParameterConfig(); - config.setProjectId(runRequest.getProjectId()); - - Map envConfig = new HashMap<>(); - Map map = runRequest.getEnvironmentMap(); - if (map != null && map.size() > 0) { - ApiTestEnvironmentWithBLOBs environment = environmentService.get(map.get(runRequest.getProjectId())); - EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); - envConfig.put(runRequest.getProjectId(), env); - config.setConfig(envConfig); - } - HashTree hashTree = runRequest.getTestElement().generateHashTree(config); - String jmxString = runRequest.getTestElement().getJmx(hashTree); - - String testName = runRequest.getName(); - - //将jmx处理封装为通用方法 - JmxInfoDTO dto = apiTestService.updateJmxString(jmxString, testName, false); - dto.setName(runRequest.getName() + ".jmx"); - return dto; + return apiTestService.getJmxInfoDTO(runRequest, bodyFiles); } } diff --git a/backend/src/main/java/io/metersphere/api/dto/JmxInfoDTO.java b/backend/src/main/java/io/metersphere/api/dto/JmxInfoDTO.java index 00ae9a2dca..3bb48daaef 100644 --- a/backend/src/main/java/io/metersphere/api/dto/JmxInfoDTO.java +++ b/backend/src/main/java/io/metersphere/api/dto/JmxInfoDTO.java @@ -18,6 +18,7 @@ public class JmxInfoDTO { private String name; private String xml; private String id; + private Integer version; private Map attachFiles; private List fileMetadataList; 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 index c97122053c..f38f7fd2b9 100644 --- a/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenrioExportJmx.java +++ b/backend/src/main/java/io/metersphere/api/dto/automation/ApiScenrioExportJmx.java @@ -10,6 +10,7 @@ import java.util.List; @Setter public class ApiScenrioExportJmx { private String name; + private String id; private String jmx; private Integer version; diff --git a/backend/src/main/java/io/metersphere/api/dto/definition/SaveApiTestCaseRequest.java b/backend/src/main/java/io/metersphere/api/dto/definition/SaveApiTestCaseRequest.java index f7d2c1c67c..7beeedbd83 100644 --- a/backend/src/main/java/io/metersphere/api/dto/definition/SaveApiTestCaseRequest.java +++ b/backend/src/main/java/io/metersphere/api/dto/definition/SaveApiTestCaseRequest.java @@ -1,6 +1,7 @@ package io.metersphere.api.dto.definition; import io.metersphere.api.dto.definition.request.MsTestElement; +import io.metersphere.base.domain.ApiTestCase; import lombok.Getter; import lombok.Setter; @@ -8,36 +9,18 @@ import java.util.List; @Setter @Getter -public class SaveApiTestCaseRequest { - - private String id; - - private String projectId; - - private String name; - - private String priority; - - private String apiDefinitionId; - - private String description; +public class SaveApiTestCaseRequest extends ApiTestCase { private MsTestElement request; + private String description; + private String response; private String crateUserId; - private String updateUserId; - - private Long createTime; - - private Long updateTime; - private List bodyUploadIds; - private String tags; - //ESB参数。 可为null private String esbDataStruct; private String backEsbDataStruct; diff --git a/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java b/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java index 33a244d1f5..8d0fc4d0ca 100644 --- a/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java +++ b/backend/src/main/java/io/metersphere/api/dto/scenario/Body.java @@ -8,6 +8,7 @@ import io.metersphere.jmeter.utils.ScriptEngineUtils; import lombok.Data; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.http.entity.ContentType; import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy; import org.apache.jmeter.protocol.http.util.HTTPFileArg; @@ -137,6 +138,9 @@ public class Body { path = FileUtils.BODY_FILE_DIR + '/' + requestId + '/' + file.getName(); } String mimetype = keyValue.getContentType(); + if (StringUtils.isBlank(mimetype)) { + mimetype = ContentType.APPLICATION_OCTET_STREAM.getMimeType(); + } list.add(new HTTPFileArg(path, paramName, mimetype)); }); } diff --git a/backend/src/main/java/io/metersphere/api/service/APITestService.java b/backend/src/main/java/io/metersphere/api/service/APITestService.java index 058ef6a3d6..f3b6fb6573 100644 --- a/backend/src/main/java/io/metersphere/api/service/APITestService.java +++ b/backend/src/main/java/io/metersphere/api/service/APITestService.java @@ -4,7 +4,10 @@ import com.alibaba.fastjson.JSONObject; import com.alibaba.nacos.client.utils.StringUtils; import io.github.ningyu.jmeter.plugin.dubbo.sample.ProviderService; import io.metersphere.api.dto.*; +import io.metersphere.api.dto.definition.RunDefinitionRequest; +import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.parse.ApiImport; +import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.request.dubbo.RegistryCenter; import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.parse.old.ApiImportParser; @@ -28,10 +31,10 @@ import io.metersphere.job.sechedule.ApiTestJob; import io.metersphere.service.FileService; import io.metersphere.service.QuotaService; import io.metersphere.service.ScheduleService; -import io.metersphere.service.UserService; import io.metersphere.track.service.TestCaseService; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; +import org.apache.jorphan.collections.HashTree; import org.aspectj.util.FileUtil; import org.dom4j.Document; import org.dom4j.DocumentHelper; @@ -50,7 +53,7 @@ import java.util.stream.Collectors; @Transactional(rollbackFor = Exception.class) public class APITestService { @Resource - private UserService userService; + private ApiTestEnvironmentService apiTestEnvironmentService; @Resource private ApiTestMapper apiTestMapper; @Resource @@ -676,4 +679,27 @@ public class APITestService { } } } + + public JmxInfoDTO getJmxInfoDTO(RunDefinitionRequest runRequest, List bodyFiles) { + ParameterConfig config = new ParameterConfig(); + config.setProjectId(runRequest.getProjectId()); + + Map envConfig = new HashMap<>(); + Map map = runRequest.getEnvironmentMap(); + if (map != null && map.size() > 0) { + ApiTestEnvironmentWithBLOBs environment = apiTestEnvironmentService.get(map.get(runRequest.getProjectId())); + EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class); + envConfig.put(runRequest.getProjectId(), env); + config.setConfig(envConfig); + } + HashTree hashTree = runRequest.getTestElement().generateHashTree(config); + String jmxString = runRequest.getTestElement().getJmx(hashTree); + + String testName = runRequest.getName(); + + //将jmx处理封装为通用方法 + JmxInfoDTO dto = updateJmxString(jmxString, testName, false); + dto.setName(runRequest.getName() + ".jmx"); + return dto; + } } 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 bc00da7ba4..238c1be1dc 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiAutomationService.java @@ -1961,6 +1961,7 @@ public class ApiAutomationService { if (StringUtils.isNotEmpty(jmx)) { ApiScenrioExportJmx scenrioExportJmx = new ApiScenrioExportJmx(item.getName(), apiTestService.updateJmxString(jmx, null, true).getXml()); JmxInfoDTO dto = apiTestService.updateJmxString(jmx, item.getName(), true); + scenrioExportJmx.setId(item.getId()); scenrioExportJmx.setVersion(item.getVersion()); //扫描需要哪些文件 scenrioExportJmx.setFileMetadataList(dto.getFileMetadataList()); 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 b484af1a80..88bd497479 100644 --- a/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java +++ b/backend/src/main/java/io/metersphere/api/service/ApiTestCaseService.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import io.metersphere.api.dto.ApiCaseBatchRequest; import io.metersphere.api.dto.DeleteCheckResult; +import io.metersphere.api.dto.JmxInfoDTO; import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.request.MsTestElement; @@ -40,6 +41,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.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -86,6 +88,9 @@ public class ApiTestCaseService { private ApiScenarioReferenceIdService apiScenarioReferenceIdService; @Resource private ExtApiScenarioMapper extApiScenarioMapper; + @Resource + @Lazy + private APITestService apiTestService; private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR; @@ -289,6 +294,7 @@ public class ApiTestCaseService { test.setPriority(request.getPriority()); test.setUpdateTime(System.currentTimeMillis()); test.setDescription(request.getDescription()); + test.setVersion(request.getVersion() == null ? 0 : request.getVersion() + 1); if (StringUtils.equals("[]", request.getTags())) { test.setTags(""); } else { @@ -930,4 +936,55 @@ public class ApiTestCaseService { result.setCheckMsg(checkMsgList); return result; } + + public List exportJmx(List caseIds, String envId) { + ApiTestCaseExample example = new ApiTestCaseExample(); + example.createCriteria().andIdIn(caseIds); + List apiTestCases = apiTestCaseMapper.selectByExampleWithBLOBs(example); + List list = new ArrayList<>(); + apiTestCases.forEach(item -> { + list.add(parse2Jmx(item, envId)); + }); + return list; + } + + private JmxInfoDTO parse2Jmx(ApiTestCaseWithBLOBs apiTestCase, String envId) { + String request = apiTestCase.getRequest(); + MsHTTPSamplerProxy msHTTPSamplerProxy = JSONObject.parseObject(request, MsHTTPSamplerProxy.class); + msHTTPSamplerProxy.setName(apiTestCase.getId()); + msHTTPSamplerProxy.setUseEnvironment(envId); + + LinkedList hashTree = new LinkedList<>(); + hashTree.add(msHTTPSamplerProxy); + MsThreadGroup msThreadGroup = new MsThreadGroup(); + msThreadGroup.setHashTree(hashTree); + msThreadGroup.setName("ThreadGroup"); + msThreadGroup.setLabel("ThreadGroup"); + msThreadGroup.setId(UUID.randomUUID().toString()); + + LinkedList planHashTree = new LinkedList<>(); + planHashTree.add(msThreadGroup); + MsTestPlan msTestPlan = new MsTestPlan(); + msTestPlan.setHashTree(planHashTree); + msTestPlan.setId(UUID.randomUUID().toString()); + msTestPlan.setName("TestPlan"); + msTestPlan.setLabel("TestPlan"); + + HashMap envMap = new HashMap<>(); + envMap.put(apiTestCase.getProjectId(), envId); + + RunDefinitionRequest runRequest = new RunDefinitionRequest(); + runRequest.setEnvironmentMap(envMap); + runRequest.setEnvironmentId(envId); + runRequest.setId(apiTestCase.getId()); + runRequest.setTestElement(msTestPlan); + runRequest.setProjectId(apiTestCase.getProjectId()); + + JmxInfoDTO jmxInfoDTO = apiTestService.getJmxInfoDTO(runRequest, new ArrayList<>()); + jmxInfoDTO.setId(apiTestCase.getId()); + jmxInfoDTO.setVersion(apiTestCase.getVersion()); + jmxInfoDTO.setName(apiTestCase.getName()); + return jmxInfoDTO; + } + } diff --git a/backend/src/main/java/io/metersphere/base/domain/ApiLoadTest.java b/backend/src/main/java/io/metersphere/base/domain/ApiLoadTest.java new file mode 100644 index 0000000000..5220fbadc0 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/ApiLoadTest.java @@ -0,0 +1,21 @@ +package io.metersphere.base.domain; + +import java.io.Serializable; +import lombok.Data; + +@Data +public class ApiLoadTest implements Serializable { + private String id; + + private String apiId; + + private String loadTestId; + + private String envId; + + private String type; + + private Integer apiVersion; + + private static final long serialVersionUID = 1L; +} diff --git a/backend/src/main/java/io/metersphere/base/domain/ApiLoadTestExample.java b/backend/src/main/java/io/metersphere/base/domain/ApiLoadTestExample.java new file mode 100644 index 0000000000..26bede932a --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/domain/ApiLoadTestExample.java @@ -0,0 +1,610 @@ +package io.metersphere.base.domain; + +import java.util.ArrayList; +import java.util.List; + +public class ApiLoadTestExample { + protected String orderByClause; + + protected boolean distinct; + + protected List oredCriteria; + + public ApiLoadTestExample() { + 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 andApiIdIsNull() { + addCriterion("api_id is null"); + return (Criteria) this; + } + + public Criteria andApiIdIsNotNull() { + addCriterion("api_id is not null"); + return (Criteria) this; + } + + public Criteria andApiIdEqualTo(String value) { + addCriterion("api_id =", value, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdNotEqualTo(String value) { + addCriterion("api_id <>", value, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdGreaterThan(String value) { + addCriterion("api_id >", value, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdGreaterThanOrEqualTo(String value) { + addCriterion("api_id >=", value, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdLessThan(String value) { + addCriterion("api_id <", value, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdLessThanOrEqualTo(String value) { + addCriterion("api_id <=", value, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdLike(String value) { + addCriterion("api_id like", value, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdNotLike(String value) { + addCriterion("api_id not like", value, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdIn(List values) { + addCriterion("api_id in", values, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdNotIn(List values) { + addCriterion("api_id not in", values, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdBetween(String value1, String value2) { + addCriterion("api_id between", value1, value2, "apiId"); + return (Criteria) this; + } + + public Criteria andApiIdNotBetween(String value1, String value2) { + addCriterion("api_id not between", value1, value2, "apiId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdIsNull() { + addCriterion("load_test_id is null"); + return (Criteria) this; + } + + public Criteria andLoadTestIdIsNotNull() { + addCriterion("load_test_id is not null"); + return (Criteria) this; + } + + public Criteria andLoadTestIdEqualTo(String value) { + addCriterion("load_test_id =", value, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdNotEqualTo(String value) { + addCriterion("load_test_id <>", value, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdGreaterThan(String value) { + addCriterion("load_test_id >", value, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdGreaterThanOrEqualTo(String value) { + addCriterion("load_test_id >=", value, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdLessThan(String value) { + addCriterion("load_test_id <", value, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdLessThanOrEqualTo(String value) { + addCriterion("load_test_id <=", value, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdLike(String value) { + addCriterion("load_test_id like", value, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdNotLike(String value) { + addCriterion("load_test_id not like", value, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdIn(List values) { + addCriterion("load_test_id in", values, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdNotIn(List values) { + addCriterion("load_test_id not in", values, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdBetween(String value1, String value2) { + addCriterion("load_test_id between", value1, value2, "loadTestId"); + return (Criteria) this; + } + + public Criteria andLoadTestIdNotBetween(String value1, String value2) { + addCriterion("load_test_id not between", value1, value2, "loadTestId"); + return (Criteria) this; + } + + public Criteria andEnvIdIsNull() { + addCriterion("env_id is null"); + return (Criteria) this; + } + + public Criteria andEnvIdIsNotNull() { + addCriterion("env_id is not null"); + return (Criteria) this; + } + + public Criteria andEnvIdEqualTo(String value) { + addCriterion("env_id =", value, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdNotEqualTo(String value) { + addCriterion("env_id <>", value, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdGreaterThan(String value) { + addCriterion("env_id >", value, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdGreaterThanOrEqualTo(String value) { + addCriterion("env_id >=", value, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdLessThan(String value) { + addCriterion("env_id <", value, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdLessThanOrEqualTo(String value) { + addCriterion("env_id <=", value, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdLike(String value) { + addCriterion("env_id like", value, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdNotLike(String value) { + addCriterion("env_id not like", value, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdIn(List values) { + addCriterion("env_id in", values, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdNotIn(List values) { + addCriterion("env_id not in", values, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdBetween(String value1, String value2) { + addCriterion("env_id between", value1, value2, "envId"); + return (Criteria) this; + } + + public Criteria andEnvIdNotBetween(String value1, String value2) { + addCriterion("env_id not between", value1, value2, "envId"); + return (Criteria) this; + } + + public Criteria andTypeIsNull() { + addCriterion("`type` is null"); + return (Criteria) this; + } + + public Criteria andTypeIsNotNull() { + addCriterion("`type` is not null"); + return (Criteria) this; + } + + public Criteria andTypeEqualTo(String value) { + addCriterion("`type` =", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotEqualTo(String value) { + addCriterion("`type` <>", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeGreaterThan(String value) { + addCriterion("`type` >", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeGreaterThanOrEqualTo(String value) { + addCriterion("`type` >=", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeLessThan(String value) { + addCriterion("`type` <", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeLessThanOrEqualTo(String value) { + addCriterion("`type` <=", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeLike(String value) { + addCriterion("`type` like", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotLike(String value) { + addCriterion("`type` not like", value, "type"); + return (Criteria) this; + } + + public Criteria andTypeIn(List values) { + addCriterion("`type` in", values, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotIn(List values) { + addCriterion("`type` not in", values, "type"); + return (Criteria) this; + } + + public Criteria andTypeBetween(String value1, String value2) { + addCriterion("`type` between", value1, value2, "type"); + return (Criteria) this; + } + + public Criteria andTypeNotBetween(String value1, String value2) { + addCriterion("`type` not between", value1, value2, "type"); + return (Criteria) this; + } + + public Criteria andApiVersionIsNull() { + addCriterion("api_version is null"); + return (Criteria) this; + } + + public Criteria andApiVersionIsNotNull() { + addCriterion("api_version is not null"); + return (Criteria) this; + } + + public Criteria andApiVersionEqualTo(Integer value) { + addCriterion("api_version =", value, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionNotEqualTo(Integer value) { + addCriterion("api_version <>", value, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionGreaterThan(Integer value) { + addCriterion("api_version >", value, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionGreaterThanOrEqualTo(Integer value) { + addCriterion("api_version >=", value, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionLessThan(Integer value) { + addCriterion("api_version <", value, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionLessThanOrEqualTo(Integer value) { + addCriterion("api_version <=", value, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionIn(List values) { + addCriterion("api_version in", values, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionNotIn(List values) { + addCriterion("api_version not in", values, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionBetween(Integer value1, Integer value2) { + addCriterion("api_version between", value1, value2, "apiVersion"); + return (Criteria) this; + } + + public Criteria andApiVersionNotBetween(Integer value1, Integer value2) { + addCriterion("api_version not between", value1, value2, "apiVersion"); + 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); + } + } +} diff --git a/backend/src/main/java/io/metersphere/base/domain/ApiTestCase.java b/backend/src/main/java/io/metersphere/base/domain/ApiTestCase.java index 7e9878fe7b..89021bfc00 100644 --- a/backend/src/main/java/io/metersphere/base/domain/ApiTestCase.java +++ b/backend/src/main/java/io/metersphere/base/domain/ApiTestCase.java @@ -37,5 +37,7 @@ public class ApiTestCase implements Serializable { private String deleteUserId; + private Integer version; + private static final long serialVersionUID = 1L; -} \ No newline at end of file +} diff --git a/backend/src/main/java/io/metersphere/base/domain/ApiTestCaseExample.java b/backend/src/main/java/io/metersphere/base/domain/ApiTestCaseExample.java index af1f3423a6..8e1fc0c53e 100644 --- a/backend/src/main/java/io/metersphere/base/domain/ApiTestCaseExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/ApiTestCaseExample.java @@ -1183,6 +1183,66 @@ public class ApiTestCaseExample { addCriterion("delete_user_id not between", value1, value2, "deleteUserId"); return (Criteria) this; } + + public Criteria andVersionIsNull() { + addCriterion("version is null"); + return (Criteria) this; + } + + public Criteria andVersionIsNotNull() { + addCriterion("version is not null"); + return (Criteria) this; + } + + public Criteria andVersionEqualTo(Integer value) { + addCriterion("version =", value, "version"); + return (Criteria) this; + } + + public Criteria andVersionNotEqualTo(Integer value) { + addCriterion("version <>", value, "version"); + return (Criteria) this; + } + + public Criteria andVersionGreaterThan(Integer value) { + addCriterion("version >", value, "version"); + return (Criteria) this; + } + + public Criteria andVersionGreaterThanOrEqualTo(Integer value) { + addCriterion("version >=", value, "version"); + return (Criteria) this; + } + + public Criteria andVersionLessThan(Integer value) { + addCriterion("version <", value, "version"); + return (Criteria) this; + } + + public Criteria andVersionLessThanOrEqualTo(Integer value) { + addCriterion("version <=", value, "version"); + return (Criteria) this; + } + + public Criteria andVersionIn(List values) { + addCriterion("version in", values, "version"); + return (Criteria) this; + } + + public Criteria andVersionNotIn(List values) { + addCriterion("version not in", values, "version"); + return (Criteria) this; + } + + public Criteria andVersionBetween(Integer value1, Integer value2) { + addCriterion("version between", value1, value2, "version"); + return (Criteria) this; + } + + public Criteria andVersionNotBetween(Integer value1, Integer value2) { + addCriterion("version not between", value1, value2, "version"); + return (Criteria) this; + } } public static class Criteria extends GeneratedCriteria { @@ -1277,4 +1337,4 @@ public class ApiTestCaseExample { this(condition, value, secondValue, null); } } -} \ No newline at end of file +} diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanTestCase.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanTestCase.java index 63a834c7d7..3f57aeab86 100644 --- a/backend/src/main/java/io/metersphere/base/domain/TestPlanTestCase.java +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanTestCase.java @@ -11,6 +11,8 @@ public class TestPlanTestCase implements Serializable { private String caseId; + private String reportId; + private String executor; private String status; @@ -21,11 +23,9 @@ public class TestPlanTestCase implements Serializable { private Long updateTime; - private String reportId; - private String createUser; private Integer issuesCount; private static final long serialVersionUID = 1L; -} \ No newline at end of file +} diff --git a/backend/src/main/java/io/metersphere/base/domain/TestPlanTestCaseExample.java b/backend/src/main/java/io/metersphere/base/domain/TestPlanTestCaseExample.java index 3498cecb28..55f91058ff 100644 --- a/backend/src/main/java/io/metersphere/base/domain/TestPlanTestCaseExample.java +++ b/backend/src/main/java/io/metersphere/base/domain/TestPlanTestCaseExample.java @@ -314,6 +314,76 @@ public class TestPlanTestCaseExample { return (Criteria) this; } + public Criteria andReportIdIsNull() { + addCriterion("report_id is null"); + return (Criteria) this; + } + + public Criteria andReportIdIsNotNull() { + addCriterion("report_id is not null"); + return (Criteria) this; + } + + public Criteria andReportIdEqualTo(String value) { + addCriterion("report_id =", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdNotEqualTo(String value) { + addCriterion("report_id <>", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdGreaterThan(String value) { + addCriterion("report_id >", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdGreaterThanOrEqualTo(String value) { + addCriterion("report_id >=", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdLessThan(String value) { + addCriterion("report_id <", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdLessThanOrEqualTo(String value) { + addCriterion("report_id <=", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdLike(String value) { + addCriterion("report_id like", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdNotLike(String value) { + addCriterion("report_id not like", value, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdIn(List values) { + addCriterion("report_id in", values, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdNotIn(List values) { + addCriterion("report_id not in", values, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdBetween(String value1, String value2) { + addCriterion("report_id between", value1, value2, "reportId"); + return (Criteria) this; + } + + public Criteria andReportIdNotBetween(String value1, String value2) { + addCriterion("report_id not between", value1, value2, "reportId"); + return (Criteria) this; + } + public Criteria andExecutorIsNull() { addCriterion("executor is null"); return (Criteria) this; @@ -644,76 +714,6 @@ public class TestPlanTestCaseExample { return (Criteria) this; } - public Criteria andReportIdIsNull() { - addCriterion("report_id is null"); - return (Criteria) this; - } - - public Criteria andReportIdIsNotNull() { - addCriterion("report_id is not null"); - return (Criteria) this; - } - - public Criteria andReportIdEqualTo(String value) { - addCriterion("report_id =", value, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdNotEqualTo(String value) { - addCriterion("report_id <>", value, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdGreaterThan(String value) { - addCriterion("report_id >", value, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdGreaterThanOrEqualTo(String value) { - addCriterion("report_id >=", value, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdLessThan(String value) { - addCriterion("report_id <", value, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdLessThanOrEqualTo(String value) { - addCriterion("report_id <=", value, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdLike(String value) { - addCriterion("report_id like", value, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdNotLike(String value) { - addCriterion("report_id not like", value, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdIn(List values) { - addCriterion("report_id in", values, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdNotIn(List values) { - addCriterion("report_id not in", values, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdBetween(String value1, String value2) { - addCriterion("report_id between", value1, value2, "reportId"); - return (Criteria) this; - } - - public Criteria andReportIdNotBetween(String value1, String value2) { - addCriterion("report_id not between", value1, value2, "reportId"); - return (Criteria) this; - } - public Criteria andCreateUserIsNull() { addCriterion("create_user is null"); return (Criteria) this; @@ -937,4 +937,4 @@ public class TestPlanTestCaseExample { this(condition, value, secondValue, null); } } -} \ No newline at end of file +} diff --git a/backend/src/main/java/io/metersphere/base/mapper/ApiLoadTestMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ApiLoadTestMapper.java new file mode 100644 index 0000000000..116b7ffcb0 --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiLoadTestMapper.java @@ -0,0 +1,30 @@ +package io.metersphere.base.mapper; + +import io.metersphere.base.domain.ApiLoadTest; +import io.metersphere.base.domain.ApiLoadTestExample; +import java.util.List; +import org.apache.ibatis.annotations.Param; + +public interface ApiLoadTestMapper { + long countByExample(ApiLoadTestExample example); + + int deleteByExample(ApiLoadTestExample example); + + int deleteByPrimaryKey(String id); + + int insert(ApiLoadTest record); + + int insertSelective(ApiLoadTest record); + + List selectByExample(ApiLoadTestExample example); + + ApiLoadTest selectByPrimaryKey(String id); + + int updateByExampleSelective(@Param("record") ApiLoadTest record, @Param("example") ApiLoadTestExample example); + + int updateByExample(@Param("record") ApiLoadTest record, @Param("example") ApiLoadTestExample example); + + int updateByPrimaryKeySelective(ApiLoadTest record); + + int updateByPrimaryKey(ApiLoadTest record); +} diff --git a/backend/src/main/java/io/metersphere/base/mapper/ApiLoadTestMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ApiLoadTestMapper.xml new file mode 100644 index 0000000000..428b518dde --- /dev/null +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiLoadTestMapper.xml @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + 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, api_id, load_test_id, env_id, `type`, api_version + + + + + delete from api_load_test + where id = #{id,jdbcType=VARCHAR} + + + delete from api_load_test + + + + + + insert into api_load_test (id, api_id, load_test_id, + env_id, `type`, api_version + ) + values (#{id,jdbcType=VARCHAR}, #{apiId,jdbcType=VARCHAR}, #{loadTestId,jdbcType=VARCHAR}, + #{envId,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{apiVersion,jdbcType=INTEGER} + ) + + + insert into api_load_test + + + id, + + + api_id, + + + load_test_id, + + + env_id, + + + `type`, + + + api_version, + + + + + #{id,jdbcType=VARCHAR}, + + + #{apiId,jdbcType=VARCHAR}, + + + #{loadTestId,jdbcType=VARCHAR}, + + + #{envId,jdbcType=VARCHAR}, + + + #{type,jdbcType=VARCHAR}, + + + #{apiVersion,jdbcType=INTEGER}, + + + + + + update api_load_test + + + id = #{record.id,jdbcType=VARCHAR}, + + + api_id = #{record.apiId,jdbcType=VARCHAR}, + + + load_test_id = #{record.loadTestId,jdbcType=VARCHAR}, + + + env_id = #{record.envId,jdbcType=VARCHAR}, + + + `type` = #{record.type,jdbcType=VARCHAR}, + + + api_version = #{record.apiVersion,jdbcType=INTEGER}, + + + + + + + + update api_load_test + set id = #{record.id,jdbcType=VARCHAR}, + api_id = #{record.apiId,jdbcType=VARCHAR}, + load_test_id = #{record.loadTestId,jdbcType=VARCHAR}, + env_id = #{record.envId,jdbcType=VARCHAR}, + `type` = #{record.type,jdbcType=VARCHAR}, + api_version = #{record.apiVersion,jdbcType=INTEGER} + + + + + + update api_load_test + + + api_id = #{apiId,jdbcType=VARCHAR}, + + + load_test_id = #{loadTestId,jdbcType=VARCHAR}, + + + env_id = #{envId,jdbcType=VARCHAR}, + + + `type` = #{type,jdbcType=VARCHAR}, + + + api_version = #{apiVersion,jdbcType=INTEGER}, + + + where id = #{id,jdbcType=VARCHAR} + + + update api_load_test + set api_id = #{apiId,jdbcType=VARCHAR}, + load_test_id = #{loadTestId,jdbcType=VARCHAR}, + env_id = #{envId,jdbcType=VARCHAR}, + `type` = #{type,jdbcType=VARCHAR}, + api_version = #{apiVersion,jdbcType=INTEGER} + where id = #{id,jdbcType=VARCHAR} + + diff --git a/backend/src/main/java/io/metersphere/base/mapper/ApiTestCaseMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ApiTestCaseMapper.xml index 00edb52dda..e3790259e7 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ApiTestCaseMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ApiTestCaseMapper.xml @@ -18,6 +18,7 @@ + @@ -82,9 +83,9 @@ - id, project_id, `name`, priority, api_definition_id, create_user_id, update_user_id, - create_time, update_time, num, tags, last_result_id, `status`, original_status, delete_time, - delete_user_id + id, project_id, `name`, priority, api_definition_id, create_user_id, update_user_id, + create_time, update_time, num, tags, last_result_id, `status`, original_status, delete_time, + delete_user_id, version description, request @@ -120,7 +121,7 @@ + select COUNT(1) from api_load_test alt + inner join api_test_case atc + on alt.type = 'API_CASE' + and alt.load_test_id = #{loadTestId} + and alt.api_id = atc.id and alt.api_version < atc.version; + + + diff --git a/backend/src/main/java/io/metersphere/commons/constants/ApiLoadType.java b/backend/src/main/java/io/metersphere/commons/constants/ApiLoadType.java new file mode 100644 index 0000000000..387bb93199 --- /dev/null +++ b/backend/src/main/java/io/metersphere/commons/constants/ApiLoadType.java @@ -0,0 +1,5 @@ +package io.metersphere.commons.constants; + +public enum ApiLoadType { + API_CASE, SCENARIO +} diff --git a/backend/src/main/java/io/metersphere/commons/utils/FileUtils.java b/backend/src/main/java/io/metersphere/commons/utils/FileUtils.java index 182d09074a..685a083300 100644 --- a/backend/src/main/java/io/metersphere/commons/utils/FileUtils.java +++ b/backend/src/main/java/io/metersphere/commons/utils/FileUtils.java @@ -79,6 +79,11 @@ public class FileUtils { return new File(path); } + public static File getBodyFileByName(String name, String requestId) { + String path = BODY_FILE_DIR + "/" + requestId + "/" + name; + return new File(path); + } + public static void copyBdyFile(String originId, String toId) { try { FileUtil.copyDir(new File(FileUtils.BODY_FILE_DIR + "/" + originId), diff --git a/backend/src/main/java/io/metersphere/listener/AppStartListener.java b/backend/src/main/java/io/metersphere/listener/AppStartListener.java index c75a2a6a64..c31dda32f4 100644 --- a/backend/src/main/java/io/metersphere/listener/AppStartListener.java +++ b/backend/src/main/java/io/metersphere/listener/AppStartListener.java @@ -6,6 +6,7 @@ import io.metersphere.api.service.ApiAutomationService; import io.metersphere.base.domain.JarConfig; import io.metersphere.commons.utils.LogUtil; import io.metersphere.commons.utils.RunInterface; +import io.metersphere.performance.service.PerformanceTestService; import io.metersphere.service.JarConfigService; import io.metersphere.service.ScheduleService; import io.metersphere.service.SystemParameterService; @@ -36,6 +37,8 @@ public class AppStartListener implements ApplicationListener updatedFileList; private Map fileSorts; private List conversionFileIdList; + private List apiList; } diff --git a/backend/src/main/java/io/metersphere/performance/request/TestPlanRequest.java b/backend/src/main/java/io/metersphere/performance/request/TestPlanRequest.java index 210ab55523..7f457b2e1d 100644 --- a/backend/src/main/java/io/metersphere/performance/request/TestPlanRequest.java +++ b/backend/src/main/java/io/metersphere/performance/request/TestPlanRequest.java @@ -26,10 +26,6 @@ public class TestPlanRequest { private String runtimeConfiguration; - private Integer scenarioVersion; - - private String scenarioId; - private Schedule schedule; private String testResourcePoolId; diff --git a/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java b/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java index 2cd2cbfc3b..fa687c2264 100644 --- a/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java +++ b/backend/src/main/java/io/metersphere/performance/service/PerformanceTestService.java @@ -1,9 +1,11 @@ package io.metersphere.performance.service; import com.alibaba.fastjson.JSON; +import io.metersphere.api.dto.JmxInfoDTO; import io.metersphere.api.dto.automation.ApiScenarioBatchRequest; import io.metersphere.api.dto.automation.ApiScenrioExportJmx; import io.metersphere.api.service.ApiAutomationService; +import io.metersphere.api.service.ApiTestCaseService; import io.metersphere.base.domain.*; import io.metersphere.base.mapper.*; import io.metersphere.base.mapper.ext.ExtLoadTestMapper; @@ -29,12 +31,16 @@ import io.metersphere.performance.dto.LoadTestExportJmx; import io.metersphere.performance.engine.Engine; import io.metersphere.performance.engine.EngineFactory; import io.metersphere.performance.request.*; +import io.metersphere.service.ApiPerformanceService; import io.metersphere.service.FileService; import io.metersphere.service.QuotaService; import io.metersphere.service.ScheduleService; import io.metersphere.track.service.TestCaseService; import org.apache.commons.collections4.ListUtils; 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.aspectj.util.FileUtil; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -87,6 +93,12 @@ public class PerformanceTestService { private TestResourcePoolMapper testResourcePoolMapper; @Resource private ApiAutomationService apiAutomationService; + @Resource + private ApiTestCaseService apiTestCaseService; + @Resource + private SqlSessionFactory sqlSessionFactory; + @Resource + private ApiPerformanceService apiPerformanceService; public List list(QueryTestPlanRequest request) { request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); @@ -213,8 +225,8 @@ public class PerformanceTestService { loadTest.setAdvancedConfiguration(request.getAdvancedConfiguration()); loadTest.setStatus(PerformanceTestStatus.Saved.name()); loadTest.setNum(getNextNum(request.getProjectId())); - loadTest.setScenarioVersion(request.getScenarioVersion()); - loadTest.setScenarioId(request.getScenarioId()); + List apiList = request.getApiList(); + apiPerformanceService.add(apiList, loadTest.getId()); loadTestMapper.insert(loadTest); return loadTest; } @@ -261,8 +273,6 @@ public class PerformanceTestService { loadTest.setAdvancedConfiguration(request.getAdvancedConfiguration()); loadTest.setTestResourcePoolId(request.getTestResourcePoolId()); loadTest.setStatus(PerformanceTestStatus.Saved.name()); - loadTest.setScenarioVersion(request.getScenarioVersion()); - loadTest.setScenarioId(request.getScenarioId()); loadTestMapper.updateByPrimaryKeySelective(loadTest); return testId; @@ -396,7 +406,7 @@ public class PerformanceTestService { List testDTOS = extLoadTestMapper.list(request); if (!CollectionUtils.isEmpty(testDTOS)) { LoadTestDTO loadTestDTO = testDTOS.get(0); - isNeedUpdate(loadTestDTO); + loadTestDTO.setIsNeedUpdate(apiPerformanceService.isNeedUpdate(loadTestDTO.getId())); Schedule schedule = scheduleService.getScheduleByResource(loadTestDTO.getId(), ScheduleGroup.PERFORMANCE_TEST.name()); loadTestDTO.setSchedule(schedule); return loadTestDTO; @@ -404,21 +414,6 @@ public class PerformanceTestService { return null; } - public void isNeedUpdate(LoadTestDTO loadTestDTO) { - String scenarioId = loadTestDTO.getScenarioId(); - if (StringUtils.isNotBlank(scenarioId)) { - ApiScenarioWithBLOBs apiScenario = apiAutomationService.getApiScenario(scenarioId); - if (apiScenario == null) { - loadTestDTO.setScenarioId(null); - } else { - if (apiScenario.getVersion() != null && loadTestDTO.getScenarioVersion() != null - && apiScenario.getVersion() > loadTestDTO.getScenarioVersion()) { - loadTestDTO.setIsNeedUpdate(true); - } - } - } - } - public String getAdvancedConfiguration(String testId) { LoadTestWithBLOBs loadTestWithBLOBs = loadTestMapper.selectByPrimaryKey(testId); return Optional.ofNullable(loadTestWithBLOBs).orElse(new LoadTestWithBLOBs()).getAdvancedConfiguration(); @@ -652,35 +647,66 @@ public class PerformanceTestService { return null; } - public void syncScenario(EditTestPlanRequest request) { - ApiScenarioBatchRequest scenarioRequest = new ApiScenarioBatchRequest(); - scenarioRequest.setIds(Arrays.asList(request.getScenarioId())); - List apiScenrioExportJmxes = apiAutomationService.exportJmx(scenarioRequest); - ApiScenrioExportJmx apiScenrioExportJmx = apiScenrioExportJmxes.get(0); - - String testId = request.getId(); - LoadTestWithBLOBs loadTest = loadTestMapper.selectByPrimaryKey(testId); + /** + * 一键更新由接口用例或者场景用例转换的性能测试 + * @param request + */ + public void syncApi(EditTestPlanRequest request) { + String lostTestId = request.getId(); + LoadTestWithBLOBs loadTest = loadTestMapper.selectByPrimaryKey(lostTestId); if (loadTest == null) { - MSException.throwException(Translator.get("edit_load_test_not_found") + testId); + MSException.throwException(Translator.get("edit_load_test_not_found") + lostTestId); } if (StringUtils.containsAny(loadTest.getStatus(), PerformanceTestStatus.Running.name(), PerformanceTestStatus.Starting.name())) { MSException.throwException(Translator.get("cannot_edit_load_test_running")); } - - loadTest.setScenarioVersion(apiScenrioExportJmx.getVersion()); - loadTest.setUpdateTime(System.currentTimeMillis()); - loadTestMapper.updateByPrimaryKeySelective(loadTest); - - deleteLoadTestFiles(testId); - saveJmxFile(apiScenrioExportJmx, loadTest.getProjectId(), loadTest.getId()); - saveOtherFile(apiScenrioExportJmx.getFileMetadataList(), loadTest.getId()); - + List apiLoadTests = apiPerformanceService.getByLoadTestId(loadTest.getId()); + syncScenario(loadTest, apiLoadTests); + syncApiCase(loadTest, apiLoadTests); } - private void saveJmxFile(ApiScenrioExportJmx apiScenrioExportJmx, String projectId, String loadTestId) { - String jmx = apiScenrioExportJmx.getJmx(); + public void syncScenario(LoadTestWithBLOBs loadTest, List apiLoadTests) { + List scenarioIds = apiLoadTests.stream() + .filter(i -> i.getType().equals(ApiLoadType.SCENARIO.name())) + .map(ApiLoadTest::getApiId) + .collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(scenarioIds)) { + ApiScenarioBatchRequest scenarioRequest = new ApiScenarioBatchRequest(); + scenarioRequest.setIds(scenarioIds); + List apiScenrioExportJmxes = apiAutomationService.exportJmx(scenarioRequest); + + deleteLoadTestFiles(loadTest.getId()); + + apiScenrioExportJmxes.forEach(item -> { + apiPerformanceService.UpdateVersion(loadTest.getId(), item.getId(), item.getVersion()); + saveJmxFile(item.getJmx(), item.getName(), loadTest.getProjectId(), loadTest.getId()); + saveOtherFile(item.getFileMetadataList(), loadTest.getId()); + }); + } + } + + public void syncApiCase(LoadTestWithBLOBs loadTest, List apiLoadTests) { + List caseIds = apiLoadTests.stream() + .filter(i -> i.getType().equals(ApiLoadType.API_CASE.name())) + .map(ApiLoadTest::getApiId) + .collect(Collectors.toList()); + if (!CollectionUtils.isEmpty(caseIds)) { + ApiScenarioBatchRequest scenarioRequest = new ApiScenarioBatchRequest(); + scenarioRequest.setIds(caseIds); + + List jmxInfoDTOS = apiTestCaseService.exportJmx(caseIds, apiLoadTests.get(0).getEnvId()); + deleteLoadTestFiles(loadTest.getId()); + jmxInfoDTOS.forEach(item -> { + apiPerformanceService.UpdateVersion(loadTest.getId(), item.getId(), item.getVersion()); + saveJmxFile(item.getXml(), item.getName(), loadTest.getProjectId(), loadTest.getId()); + saveBodyFile(item.getFileMetadataList(), loadTest.getId(), item.getId()); + }); + } + } + + private void saveJmxFile(String jmx, String name, String projectId, String loadTestId) { byte[] jmxBytes = jmx.getBytes(StandardCharsets.UTF_8); - String jmxName = apiScenrioExportJmx.getName() + "_" + System.currentTimeMillis() + ".jmx"; + String jmxName = name + "_" + System.currentTimeMillis() + ".jmx"; FileMetadata fileMetadata = fileService.saveFile(jmxBytes, jmxName, (long) jmxBytes.length); fileMetadata.setProjectId(projectId); saveLoadTestFile(fileMetadata, loadTestId, 0); @@ -695,6 +721,14 @@ public class PerformanceTestService { } } + private void saveBodyFile(List fileNames, String loadTestId, String requestId) { + for (int i = 0; i < fileNames.size(); i++) { + String fileName = fileNames.get(i).getName(); + File file = FileUtils.getBodyFileByName(fileName, requestId); + saveUploadFile(file, loadTestId, i + 1); + } + } + private void deleteLoadTestFiles(String testId) { List originFiles = getFileMetadataByTestId(testId); List originFileIds = originFiles.stream().map(FileMetadata::getId).collect(Collectors.toList()); @@ -726,4 +760,24 @@ public class PerformanceTestService { loadTestFileMapper.insert(loadTestFile); } } + + /** + * 初始化场景与性能测试的关联关系 + */ + public void initScenarioLoadTest() { + LoadTestExample example = new LoadTestExample(); + example.createCriteria().andScenarioIdIsNotNull(); + List loadTests = loadTestMapper.selectByExample(example); + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + ApiLoadTestMapper mapper = sqlSession.getMapper(ApiLoadTestMapper.class); + loadTests.forEach(item -> { + ApiLoadTest scenarioLoadTest = new ApiLoadTest(); + scenarioLoadTest.setType(ApiLoadType.SCENARIO.name()); + scenarioLoadTest.setApiId(item.getScenarioId()); + scenarioLoadTest.setApiVersion(item.getScenarioVersion() == null ? 0 : item.getScenarioVersion()); + scenarioLoadTest.setLoadTestId(item.getId()); + scenarioLoadTest.setId(UUID.randomUUID().toString()); + mapper.insert(scenarioLoadTest); + }); + } } diff --git a/backend/src/main/java/io/metersphere/service/ApiPerformanceService.java b/backend/src/main/java/io/metersphere/service/ApiPerformanceService.java new file mode 100644 index 0000000000..9eab0c6392 --- /dev/null +++ b/backend/src/main/java/io/metersphere/service/ApiPerformanceService.java @@ -0,0 +1,59 @@ +package io.metersphere.service; + +import io.metersphere.base.domain.ApiLoadTest; +import io.metersphere.base.domain.ApiLoadTestExample; +import io.metersphere.base.mapper.ApiLoadTestMapper; +import io.metersphere.base.mapper.ext.ExtApiLoadTestMapper; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.List; +import java.util.UUID; + +@Service +@Transactional(rollbackFor = Exception.class) +public class ApiPerformanceService { + + @Resource + private ApiLoadTestMapper apiLoadTestMapper; + @Resource + private ExtApiLoadTestMapper extApiLoadTestMapper; + + public boolean isNeedUpdate(String loadTestId) { + int count = extApiLoadTestMapper.countNeedUpdateApiCase(loadTestId); + if (count > 0) { + return true; + } + count = extApiLoadTestMapper.countNeedUpdateApiScenario(loadTestId); + return count > 0 ? true : false; + } + + public List getByLoadTestId(String loadTestId) { + ApiLoadTestExample example = new ApiLoadTestExample(); + example.createCriteria().andLoadTestIdEqualTo(loadTestId); + return apiLoadTestMapper.selectByExample(example); + } + + public int UpdateVersion(String loadTestId, String apiId, int version) { + ApiLoadTest apiLoadTest = new ApiLoadTest(); + apiLoadTest.setApiVersion(version); + ApiLoadTestExample example = new ApiLoadTestExample(); + example.createCriteria() + .andLoadTestIdEqualTo(loadTestId) + .andApiIdEqualTo(apiId); + return apiLoadTestMapper.updateByExampleSelective(apiLoadTest, example); + } + + public void add(List apiList, String loadTestId) { + if (CollectionUtils.isNotEmpty(apiList)) { + apiList.forEach(item -> { + item.setId(UUID.randomUUID().toString()); + item.setLoadTestId(loadTestId); + item.setApiVersion(0); + apiLoadTestMapper.insert(item); + }); + } + } +} diff --git a/backend/src/main/resources/db/migration/V92__v1.11.2_release.sql b/backend/src/main/resources/db/migration/V92__v1.11.2_release.sql index d9fd6250b7..9ac2eb76b5 100644 --- a/backend/src/main/resources/db/migration/V92__v1.11.2_release.sql +++ b/backend/src/main/resources/db/migration/V92__v1.11.2_release.sql @@ -26,4 +26,20 @@ CREATE TABLE `load_test_report_detail` ) ENGINE = MyISAM DEFAULT CHARSET = utf8mb4 - COLLATE utf8mb4_general_ci; \ No newline at end of file + COLLATE utf8mb4_general_ci; + + +-- 关联场景测试和性能测试,一键更新性能测试 +CREATE TABLE IF NOT EXISTS `api_load_test` ( + `id` varchar(50) NOT NULL COMMENT 'ID', + `api_id` varchar(255) NOT NULL COMMENT 'Relate resource id', + `load_test_id` varchar(50) NOT NULL COMMENT 'Load Test id', + `env_id` varchar(50) NULL COMMENT 'Api case env id', + `type` varchar(20) NOT NULL COMMENT 'Api Type', + `api_version` int(10) DEFAULT 0 NULL COMMENT 'Relate Scenario Version', + PRIMARY KEY (`id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE utf8mb4_general_ci; + +-- 添加版本号 +ALTER TABLE api_test_case + ADD version INT(10) DEFAULT 0 NULL COMMENT '版本号'; diff --git a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue index 5efe8f43a5..d820ecb504 100644 --- a/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue +++ b/frontend/src/business/components/api/automation/scenario/ApiScenarioList.vue @@ -979,6 +979,7 @@ export default { jmxObj.attachFiles = item.attachFiles; jmxObj.attachByteFiles = item.attachByteFiles; jmxObj.scenarioId = item.id; + jmxObj.version = item.version; jmxObjList.push(jmxObj); }); this.$store.commit('setScenarioJmxs', { diff --git a/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue b/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue index f3acc24e68..d8cb7f6fb2 100644 --- a/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue +++ b/frontend/src/business/components/api/definition/components/list/ApiCaseSimpleList.vue @@ -968,6 +968,8 @@ export default { jmxObj.attachFiles = response.data.attachFiles; jmxObj.attachByteFiles = response.data.attachByteFiles; jmxObj.caseId = reqObj.id; + jmxObj.version = row.version; + jmxObj.envId = environment.id; this.$store.commit('setTest', { name: row.name, jmx: jmxObj diff --git a/frontend/src/business/components/api/definition/components/reference/ApiExtendBtns.vue b/frontend/src/business/components/api/definition/components/reference/ApiExtendBtns.vue index 1b865d6350..00d1d84c8e 100644 --- a/frontend/src/business/components/api/definition/components/reference/ApiExtendBtns.vue +++ b/frontend/src/business/components/api/definition/components/reference/ApiExtendBtns.vue @@ -5,7 +5,7 @@ {{ $t('api_test.automation.view_ref') }} - {{ $t('api_test.create_performance_test') }} + {{ $t('api_test.create_performance_test') }} @@ -93,6 +93,8 @@ jmxObj.attachFiles = response.data.attachFiles; jmxObj.attachByteFiles = response.data.attachByteFiles; jmxObj.caseId = reqObj.id; + jmxObj.version = row.version; + jmxObj.envId = this.environment; this.$store.commit('setTest', { name: row.name, jmx: jmxObj diff --git a/frontend/src/business/components/performance/test/EditPerformanceTest.vue b/frontend/src/business/components/performance/test/EditPerformanceTest.vue index e4adc1eee6..2d68cf1531 100644 --- a/frontend/src/business/components/performance/test/EditPerformanceTest.vue +++ b/frontend/src/business/components/performance/test/EditPerformanceTest.vue @@ -32,7 +32,7 @@ v-permission="['PROJECT_PERFORMANCE_TEST:READ+SCHEDULE']" :check-open="checkScheduleEdit" :test-id="testId" :custom-validate="durationValidate"/> - { if (item.scenarioId) { this.$refs.basicConfig.importScenario(item.scenarioId); this.$refs.basicConfig.handleUpload(); + relateApiList.push({ + apiId : item.scenarioId, + apiVersion: item.version, + type: 'SCENARIO' + }); } if (item.caseId) { this.$refs.basicConfig.importCase(item); @@ -195,6 +214,7 @@ export default { this.$refs.basicConfig.selectAttachFileById(attachFiles); } } + this.$set(this.test, "apiList", relateApiList); }); this.active = '1'; this.$store.commit("clearScenarioJmxs");