refactor(接口测试): 优化场景报告
This commit is contained in:
parent
c06287bbbc
commit
4cef3121d9
|
@ -46,6 +46,8 @@ public class ApiScenarioReportStepDTO {
|
|||
|
||||
@Schema(description = "脚本标识")
|
||||
private String scriptIdentifier;
|
||||
@Schema(description = "循环控制器步骤的排序")
|
||||
private Long loopIndex;
|
||||
|
||||
@Schema(description = "子节点")
|
||||
private List<ApiScenarioReportStepDTO> children;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -47,16 +47,16 @@ public class ResponseHeaderAssertionConverter extends AssertionConverter<MsRespo
|
|||
}
|
||||
String expectedValue = msAssertion.getExpectedValue();
|
||||
String condition = msAssertion.getCondition();
|
||||
assertion.setName(String.format("Response header %s %s", condition.toLowerCase().replace("_", ""), expectedValue));
|
||||
MsAssertionCondition msAssertionCondition = EnumValidator.validateEnum(MsAssertionCondition.class, condition);
|
||||
String header = msAssertion.getHeader();
|
||||
String testString = switch (msAssertionCondition) {
|
||||
case CONTAINS -> 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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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<ApiScenarioReport> reports, List<ApiScenarioRecord> records) {
|
||||
|
@ -245,6 +246,27 @@ public class ApiScenarioReportService {
|
|||
for (ApiScenarioReportStepDTO step : steps) {
|
||||
List<ApiScenarioReportStepDTO> children = scenarioReportStepMap.get(step.getStepId());
|
||||
if (CollectionUtils.isNotEmpty(children)) {
|
||||
//如果是循环控制器 需要重新处理
|
||||
if (StringUtils.equals(ApiScenarioStepType.LOOP_CONTROLLER.name(), step.getStepType())) {
|
||||
//根据stepId进行分组
|
||||
Map<String, List<ApiScenarioReportStepDTO>> loopMap = children.stream().collect(Collectors.groupingBy(ApiScenarioReportStepDTO::getStepId));
|
||||
List<ApiScenarioReportStepDTO> 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<ApiScenarioReportDetailDTO> 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<ApiScenarioReportDetail> 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<ApiScenarioReportDetailDTO> results = new ArrayList<>();
|
||||
apiReportDetails.forEach(apiReportDetail -> {
|
||||
ApiScenarioReportDetailDTO apiReportDetailDTO = new ApiScenarioReportDetailDTO();
|
||||
|
|
|
@ -393,6 +393,25 @@ public class ApiScenarioReportControllerTests extends BaseTest {
|
|||
List<ApiScenarioReportDTO> 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\":\"<!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&tpl=mn&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>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <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());
|
||||
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());
|
||||
|
|
Loading…
Reference in New Issue