refactor(接口测试): 优化场景报告

This commit is contained in:
wxg0103 2024-03-21 11:27:29 +08:00 committed by Craftsman
parent 121d03127f
commit 47e43aa847
3 changed files with 70 additions and 9 deletions

View File

@ -35,5 +35,9 @@ public enum ApiScenarioStepType {
* 一次控制器
*/
ONCE_ONLY_CONTROLLER,
/**
* 等待控制器
*/
CONSTANT_TIMER,
}

View File

@ -1,5 +1,6 @@
package io.metersphere.api.service.scenario;
import io.metersphere.api.constants.ApiScenarioStepType;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.definition.ApiReportBatchRequest;
import io.metersphere.api.dto.definition.ApiReportPageRequest;
@ -9,6 +10,7 @@ import io.metersphere.api.dto.scenario.ApiScenarioReportDetailDTO;
import io.metersphere.api.dto.scenario.ApiScenarioReportStepDTO;
import io.metersphere.api.mapper.*;
import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.sdk.constants.ApiReportStatus;
import io.metersphere.sdk.dto.api.result.RequestResult;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.mapper.EnvironmentMapper;
@ -203,16 +205,44 @@ public class ApiScenarioReportService {
}
private static void getStepTree(List<ApiScenarioReportStepDTO> steps, Map<String, List<ApiScenarioReportStepDTO>> scenarioReportStepMap) {
steps.forEach(step -> {
List<ApiScenarioReportStepDTO> children = scenarioReportStepMap.get(step.getStepId());
if (CollectionUtils.isNotEmpty(children)) {
//如果是父级的报告需要计算请求时间 请求时间是所有子级的请求时间之和 还需要计算请求的大小 还有请求的数量 以及请求成功的状态
if (CollectionUtils.isNotEmpty(steps)) {
List<String> stepTypes = Arrays.asList(ApiScenarioStepType.IF_CONTROLLER.name(),
ApiScenarioStepType.LOOP_CONTROLLER.name(),
ApiScenarioStepType.ONCE_ONLY_CONTROLLER.name(),
ApiScenarioStepType.CONSTANT_TIMER.name());
for (ApiScenarioReportStepDTO step : steps) {
List<ApiScenarioReportStepDTO> children = scenarioReportStepMap.get(step.getStepId());
if (CollectionUtils.isNotEmpty(children)) {
children.sort(Comparator.comparingLong(ApiScenarioReportStepDTO::getSort));
step.setChildren(children);
getStepTree(children, scenarioReportStepMap);
//如果是父级的报告需要计算请求时间 请求时间是所有子级的请求时间之和 还需要计算请求的大小 还有请求的数量 以及请求成功的状态
step.setRequestTime(step.getChildren().stream().mapToLong(child -> child.getRequestTime() != null ? child.getRequestTime() : 0).sum());
step.setResponseSize(step.getChildren().stream().mapToLong(child -> child.getResponseSize() != null ? child.getResponseSize() : 0).sum());
//请求的状态 如果是 LOOP_CONTROLLER IF_CONTROLLER ONCE_ONLY_CONTROLLER 则需要判断子级的状态 但是如果下面没有子集不需要判断状态
//需要把这些数据拿出来 如果没有子请求说明是最后一级的请求 不需要计算入状态
//children 先过滤满足控制器的数据然后再获取id
List<String> controllerIds = children.stream().filter(child -> stepTypes.contains(child.getStepType())).map(ApiScenarioReportStepDTO::getStepId).toList();
//看map中有没有这些id 如果没有 需要返回几个没有
List<String> noControllerIds = controllerIds.stream().filter(controllerId -> !scenarioReportStepMap.containsKey(controllerId)).toList();
//获取所有的子请求的状态
List<String> requestStatus = children.stream().map(ApiScenarioReportStepDTO::getStatus).toList();
//过滤出来SUCCESS的状态
List<String> successStatus = requestStatus.stream().filter(status -> StringUtils.equals(ApiReportStatus.SUCCESS.name(),status)).toList();
//只要包含ERROR 就是ERROR
if (requestStatus.contains(ApiReportStatus.ERROR.name())) {
step.setStatus(ApiReportStatus.ERROR.name());
} else if (requestStatus.contains(ApiReportStatus.FAKE_ERROR.name())) {
step.setStatus(ApiReportStatus.FAKE_ERROR.name());
} else if (successStatus.size() == children.size()- noControllerIds.size()) {
step.setStatus(ApiReportStatus.SUCCESS.name());
} else {
step.setStatus(ApiReportStatus.PENDING.name());
}
children.sort(Comparator.comparingLong(ApiScenarioReportStepDTO::getSort));
step.setChildren(children);
getStepTree(children, scenarioReportStepMap);
}
}
});
}
}
public List<ApiScenarioReportDetailDTO> getDetail(String stepId, String reportId) {

View File

@ -1,5 +1,6 @@
package io.metersphere.api.controller;
import io.metersphere.api.constants.ApiScenarioStepType;
import io.metersphere.api.constants.ShareInfoType;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.definition.ApiReportBatchRequest;
@ -272,17 +273,43 @@ public class ApiScenarioReportControllerTests extends BaseTest {
apiScenarioReportStep.setStepId("test-scenario-report-step-id" + i);
apiScenarioReportStep.setReportId("test-scenario-report-id");
apiScenarioReportStep.setSort((long) i);
apiScenarioReportStep.setStepType("case");
if (i % 2 == 0) {
apiScenarioReportStep.setStepType(ApiScenarioStepType.API_CASE.name());
apiScenarioReportStep.setParentId("NONE");
} else if (i % 3 == 0) {
apiScenarioReportStep.setStepType(ApiScenarioStepType.IF_CONTROLLER.name());
apiScenarioReportStep.setParentId("test-scenario-report-step-id" + (i - 1));
} else {
apiScenarioReportStep.setStepType(ApiScenarioStepType.API_SCENARIO.name());
apiScenarioReportStep.setParentId("test-scenario-report-step-id" + (i - 2));
}
steps.add(apiScenarioReportStep);
}
apiScenarioReportService.insertApiScenarioReportStep(steps);
List<ApiScenarioReportDetail> details = new ArrayList<>();
for (int i = 1; i < 20; i++) {
ApiScenarioReportDetail apiReportDetail = new ApiScenarioReportDetail();
apiReportDetail.setId("test-report-detail-id" + i+2);
apiReportDetail.setReportId("test-scenario-report-id");
apiReportDetail.setStepId("test-scenario-report-step-id" + i);
if (i % 2 == 0) {
apiReportDetail.setStatus(ApiReportStatus.SUCCESS.name());
apiReportDetail.setResponseSize(1L);
apiReportDetail.setRequestTime(2L);
} else if (i % 3 == 0){
apiReportDetail.setStatus(null);
apiReportDetail.setResponseSize(0L);
apiReportDetail.setRequestTime(2L);
} else {
apiReportDetail.setStatus(ApiReportStatus.FAKE_ERROR.name());
apiReportDetail.setResponseSize(1L);
apiReportDetail.setRequestTime(2L);
}
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\":\"<!DOCTYPE html>\\r\\n<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class=\\\"bg s_ipt_wr\\\"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class=\\\"bg s_btn_wr\\\"><input type=submit id=su value=百度一下 class=\\\"bg s_btn\\\" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&amp;tpl=mn&amp;u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href=\\\"http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === \\\"\\\" ? \\\"?\\\" : \\\"&\\\")+ \\\"bdorz_come=1\\\")+ '\\\" name=\\\"tj_login\\\" class=\\\"lb\\\">登录</a>');\\r\\n </script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style=\\\"display: block;\\\">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>&copy;2017&nbsp;Baidu&nbsp;<a href=http://www.baidu.com/duty/>使用百度前必读</a>&nbsp; <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a>&nbsp;京ICP证030173号&nbsp; <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>\\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());
details.add(apiReportDetail);
}
apiScenarioReportDetailMapper.batchInsert(details);
//插入console 资源池 环境
ApiScenarioReportLog apiScenarioReportLog = new ApiScenarioReportLog();