From 4cef3121d91044208f846131c956d2ce00e041ba Mon Sep 17 00:00:00 2001 From: wxg0103 <727495428@qq.com> Date: Thu, 28 Mar 2024 17:51:42 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E5=9C=BA=E6=99=AF=E6=8A=A5=E5=91=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scenario/ApiScenarioReportStepDTO.java | 2 ++ .../api/mapper/ExtApiScenarioReportMapper.xml | 3 +- .../ResponseHeaderAssertionConverter.java | 8 ++--- .../body/JSONPathAssertionConverter.java | 2 +- .../body/RegexAssertionConverter.java | 2 +- .../body/XPathAssertionConverter.java | 2 +- .../scenario/ApiScenarioReportService.java | 34 +++++++++++++++++++ .../ApiScenarioReportControllerTests.java | 19 +++++++++++ 8 files changed, 64 insertions(+), 8 deletions(-) diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioReportStepDTO.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioReportStepDTO.java index 724c632eca..724390a5f4 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioReportStepDTO.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioReportStepDTO.java @@ -46,6 +46,8 @@ public class ApiScenarioReportStepDTO { @Schema(description = "脚本标识") private String scriptIdentifier; + @Schema(description = "循环控制器步骤的排序") + private Long loopIndex; @Schema(description = "子节点") private List children; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.xml b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.xml index ed56749374..7fbca017d2 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.xml +++ b/backend/services/api-test/src/main/java/io/metersphere/api/mapper/ExtApiScenarioReportMapper.xml @@ -80,7 +80,8 @@ api_scenario_report_detail.request_time, api_scenario_report_detail.code, api_scenario_report_detail.response_size, - api_scenario_report_detail.script_identifier + api_scenario_report_detail.script_identifier, + api_scenario_report_detail.sort as loopIndex from api_scenario_report_step left join api_scenario_report_detail on api_scenario_report_step.step_id = api_scenario_report_detail.step_id diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/ResponseHeaderAssertionConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/ResponseHeaderAssertionConverter.java index 3640da3634..d847ca4251 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/ResponseHeaderAssertionConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/ResponseHeaderAssertionConverter.java @@ -47,16 +47,16 @@ public class ResponseHeaderAssertionConverter extends AssertionConverter StringUtils.join("\\b", msAssertion.getHeader(),": .*", expectedValue, ".*\\b"); - case NOT_CONTAINS -> StringUtils.join("\\b", msAssertion.getHeader(),": (?!.*", expectedValue, ").*\\b"); + case CONTAINS -> StringUtils.join("\\b", header,": .*", expectedValue, ".*\\b"); + case NOT_CONTAINS -> StringUtils.join("\\b", header,": (?!.*", expectedValue, ").*\\b"); case EQUALS -> StringUtils.join("\\b", header,": ",expectedValue, "\\b"); - case NOT_EQUALS -> StringUtils.join("\\b", msAssertion.getHeader(),": (?!", expectedValue,"\\b)\\d+"); + case NOT_EQUALS -> StringUtils.join("\\b", header,": (?!", expectedValue,"\\b)\\d+"); default -> expectedValue; }; + assertion.setName(String.format("Response header %s %s %s", header, condition.toLowerCase().replace("_", ""), expectedValue)); assertion.addTestString(testString); assertion.setToContainsType(); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/JSONPathAssertionConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/JSONPathAssertionConverter.java index f18d22f8de..5bef16adf6 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/JSONPathAssertionConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/JSONPathAssertionConverter.java @@ -34,7 +34,7 @@ public class JSONPathAssertionConverter extends ResponseBodyTypeAssertionConvert String condition = msAssertion.getCondition(); String expression = msAssertion.getExpression(); String expectedValue = msAssertion.getExpectedValue(); - assertion.setName(String.format("Response date JSONPath expect %s %s %s", expression, condition.toLowerCase().replace("_", ""), expectedValue)); + assertion.setName(String.format("Response data JSONPath expect %s %s %s", expression, condition.toLowerCase().replace("_", ""), expectedValue)); if (BooleanUtils.isFalse(globalEnable)) { // 如果整体禁用,则禁用 assertion.setEnabled(false); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/RegexAssertionConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/RegexAssertionConverter.java index 47a6366f20..7a355d1b82 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/RegexAssertionConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/RegexAssertionConverter.java @@ -32,7 +32,7 @@ public class RegexAssertionConverter extends ResponseBodyTypeAssertionConverter< private ResponseAssertion parse2RegexResponseAssertion(MsRegexAssertionItem msAssertion, Boolean globalEnable) { ResponseAssertion assertion = AssertionConverter.createResponseAssertion(); assertion.setEnabled(msAssertion.getEnable()); - assertion.setName("Response date expect regex " + msAssertion.getExpression()); + assertion.setName("Response data expect regex " + msAssertion.getExpression()); assertion.addTestString(msAssertion.getExpression()); assertion.setTestFieldResponseData(); if (BooleanUtils.isFalse(globalEnable)) { diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/XPathAssertionConverter.java b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/XPathAssertionConverter.java index 5fee9ab670..b110a886cd 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/XPathAssertionConverter.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/parser/jmeter/processor/assertion/body/XPathAssertionConverter.java @@ -46,7 +46,7 @@ public class XPathAssertionConverter extends ResponseBodyTypeAssertionConverter< assertion.setEnabled(msAssertion.getEnable()); assertion.setTolerant(true); assertion.setValidating(false); - assertion.setName("Response date expect xpath " + msAssertion.getExpression()); + assertion.setName("Response data expect xpath " + msAssertion.getExpression()); assertion.setProperty(TestElement.TEST_CLASS, XPathAssertion.class.getName()); assertion.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass(XPATH_ASSERTION_GUI)); assertion.setXPathString(msAssertion.getExpression()); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioReportService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioReportService.java index 464ef168b0..4b42af0a2b 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioReportService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioReportService.java @@ -68,6 +68,7 @@ public class ApiScenarioReportService { private EnvironmentGroupMapper environmentGroupMapper; @Resource private UserMapper userMapper; + private static final String SPLITTER = "_"; @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) public void insertApiScenarioReport(List reports, List records) { @@ -245,6 +246,27 @@ public class ApiScenarioReportService { for (ApiScenarioReportStepDTO step : steps) { List children = scenarioReportStepMap.get(step.getStepId()); if (CollectionUtils.isNotEmpty(children)) { + //如果是循环控制器 需要重新处理 + if (StringUtils.equals(ApiScenarioStepType.LOOP_CONTROLLER.name(), step.getStepType())) { + //根据stepId进行分组 + Map> loopMap = children.stream().collect(Collectors.groupingBy(ApiScenarioReportStepDTO::getStepId)); + List newChildren = new ArrayList<>(); + loopMap.forEach((key, value) -> { + ApiScenarioReportStepDTO loopStep = new ApiScenarioReportStepDTO(); + BeanUtils.copyBean(loopStep, value.getFirst()); + newChildren.add(loopStep); + value.sort(Comparator.comparingLong(ApiScenarioReportStepDTO::getLoopIndex)); + for (int i = 0; i < value.size(); i++) { + ApiScenarioReportStepDTO loop = value.get(i); + loop.setSort((long) i+1); + loop.setParentId(key); + loop.setStepId(loopStep.getStepId() + SPLITTER + loop.getSort()); + } + scenarioReportStepMap.put(key, value); + }); + children = newChildren; + scenarioReportStepMap.remove(step.getStepId()); + } children.sort(Comparator.comparingLong(ApiScenarioReportStepDTO::getSort)); step.setChildren(children); getStepTree(children, scenarioReportStepMap); @@ -282,7 +304,19 @@ public class ApiScenarioReportService { } public List getDetail(String reportId, String stepId) { + //如果是循环控制器下的步骤id 会带着第几条 需要分割处理 + String index = null; + if (StringUtils.isNotBlank(stepId) && StringUtils.contains(stepId, SPLITTER)) { + index = StringUtils.substringAfter(stepId, SPLITTER); + stepId = StringUtils.substringBefore(stepId, SPLITTER); + } List apiReportDetails = checkResourceStep(stepId, reportId); + apiReportDetails.sort(Comparator.comparingLong(ApiScenarioReportDetail::getSort)); + + if (StringUtils.isNotBlank(index)) { + ApiScenarioReportDetail apiScenarioReportDetail = apiReportDetails.get(Integer.parseInt(index) -1); + apiReportDetails = Collections.singletonList(apiScenarioReportDetail); + } List results = new ArrayList<>(); apiReportDetails.forEach(apiReportDetail -> { ApiScenarioReportDetailDTO apiReportDetailDTO = new ApiScenarioReportDetailDTO(); diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioReportControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioReportControllerTests.java index 569ccfb7da..b0eed37a21 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioReportControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioReportControllerTests.java @@ -393,6 +393,25 @@ public class ApiScenarioReportControllerTests extends BaseTest { List data = ApiDataUtils.parseArray(JSON.toJSONString(parseResponse(mvcResult).get("data")), ApiScenarioReportDTO.class); Assertions.assertNotNull(data); + reports = new ArrayList<>(); + for (int i = 0; i < 2; i++) { + ApiScenarioReportDetail apiReportDetail = new ApiScenarioReportDetail(); + apiReportDetail.setId("test-report-detail-id-loop" + i); + apiReportDetail.setReportId("test-report-detail-id-loop"); + apiReportDetail.setStepId("test-report-detail-id-loop"); + apiReportDetail.setStatus("success"); + apiReportDetail.setResponseSize(0L); + apiReportDetail.setRequestTime((long) i); + apiReportDetail.setSort((long) i); + apiReportDetail.setContent("{\"resourceId\":\"\",\"stepId\":null,\"threadName\":\"Thread Group\",\"name\":\"HTTP Request1\",\"url\":\"https://www.baidu.com/\",\"requestSize\":195,\"startTime\":1705570589125,\"endTime\":1705570589310,\"error\":1,\"headers\":\"Connection: keep-alive\\nContent-Length: 0\\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\\nHost: www.baidu.com\\nUser-Agent: Apache-HttpClient/4.5.14 (Java/21)\\n\",\"cookies\":\"\",\"body\":\"POST https://www.baidu.com/\\n\\nPOST data:\\n\\n\\n[no cookies]\\n\",\"status\":\"ERROR\",\"method\":\"POST\",\"assertionTotal\":1,\"passAssertionsTotal\":0,\"subRequestResults\":[],\"responseResult\":{\"responseCode\":\"200\",\"responseMessage\":\"OK\",\"responseTime\":185,\"latency\":180,\"responseSize\":2559,\"headers\":\"HTTP/1.1 200 OK\\nContent-Length: 2443\\nContent-Type: text/html\\nServer: bfe\\nDate: Thu, 18 Jan 2024 09:36:29 GMT\\n\",\"body\":\"\\r\\n 百度一下,你就知道

关于百度 About Baidu

©2017 Baidu 使用百度前必读  意见反馈 京ICP证030173号 

\\r\\n\",\"contentType\":\"text/html\",\"vars\":null,\"imageUrl\":null,\"socketInitTime\":14,\"dnsLookupTime\":0,\"tcpHandshakeTime\":0,\"sslHandshakeTime\":0,\"transferStartTime\":166,\"downloadTime\":5,\"bodySize\":2443,\"headerSize\":116,\"assertions\":[{\"name\":\"JSON Assertion\",\"content\":null,\"script\":null,\"message\":\"Expected to find an object with property ['test'] in path $ but found 'java.lang.String'. This is not a json object according to the JsonProvider: 'com.jayway.jsonpath.spi.json.JsonSmartJsonProvider'.\",\"pass\":false}]},\"isSuccessful\":false,\"fakeErrorMessage\":\"\",\"fakeErrorCode\":null}\n".getBytes()); + reports.add(apiReportDetail); + } + apiScenarioReportDetailMapper.batchInsert(reports); + + mockMvc.perform(getRequestBuilder(DETAIL + "test-report-detail-id-loop" + "/" + "test-report-detail-id-loop_2")) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + mockMvc.perform(getRequestBuilder(DETAIL + "test" + "/" + "test")) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk());