feat: UI报告处理

This commit is contained in:
chenjianxing 2022-04-11 16:47:55 +08:00 committed by jianxing
parent a974dafb81
commit 9c222f0aea
9 changed files with 89 additions and 47 deletions

View File

@ -16,4 +16,5 @@ public class ApiScenarioReportBaseInfoDTO {
private long reqStartTime;
private String rspCode;
private long rspTime;
private String uiImg;
}

View File

@ -14,6 +14,8 @@ import java.util.Map;
@Setter
public class RequestResultExpandDTO extends RequestResult {
private String status;
private String uiImg;
private long time;
private Map<String, String> attachInfoMap;
public RequestResultExpandDTO() {
@ -27,6 +29,9 @@ public class RequestResultExpandDTO extends RequestResult {
this.setSuccess(dto.isReqSuccess());
this.setError(dto.getReqError());
this.setStartTime(dto.getReqStartTime());
this.setTime(dto.getRspTime());
this.setEndTime(dto.getRspTime() - dto.getReqStartTime());
this.setUiImg(dto.getUiImg());
ResponseResult responseResult = this.getResponseResult();
responseResult.setResponseCode(dto.getRspCode());
responseResult.setResponseTime(dto.getRspTime());

View File

@ -10,6 +10,8 @@ import java.util.List;
@Data
public class StepTreeDTO {
private String type;
// ui 指令的类型
private String cmdType;
private int index;
private String resourceId;
private String label;

View File

@ -93,6 +93,19 @@ public class ApiScenarioReportResultService {
}
private ApiScenarioReportResultWithBLOBs newUiScenarioReportResult(String reportId, String resourceId, JSONObject value) {
ApiScenarioReportResultWithBLOBs report = newScenarioReportResult(reportId, resourceId);
String status = value.getBooleanValue("success") ? ExecuteResult.Success.name() : ExecuteResult.Error.name();
report.setStatus(status);
RequestResult result = JSONObject.parseObject(value.toJSONString(), RequestResult.class);
ApiScenarioReportBaseInfoDTO baseInfo = getBaseInfo(result);
baseInfo.setRspTime(result.getEndTime() - result.getStartTime());
baseInfo.setUiImg(result.getUrl());
report.setBaseInfo(JSONObject.toJSONString(baseInfo));
report.setContent(value.toJSONString().getBytes(StandardCharsets.UTF_8));
return report;
}
private ApiScenarioReportResultWithBLOBs newScenarioReportResult(String reportId, String resourceId) {
ApiScenarioReportResultWithBLOBs report = new ApiScenarioReportResultWithBLOBs();
report.setId(UUID.randomUUID().toString());
report.setResourceId(resourceId);
@ -100,33 +113,11 @@ public class ApiScenarioReportResultService {
report.setTotalAssertions(0L);
report.setPassAssertions(0L);
report.setCreateTime(System.currentTimeMillis());
String status = value.getBooleanValue("success") ? ExecuteResult.Success.name() : ExecuteResult.Error.name();
report.setStatus(status);
report.setContent(value.toJSONString().getBytes(StandardCharsets.UTF_8));
return report;
}
private ApiScenarioReportResultWithBLOBs newApiScenarioReportResult(String reportId, RequestResult baseResult) {
ApiScenarioReportResultWithBLOBs report = new ApiScenarioReportResultWithBLOBs();
//解析误报内容
ErrorReportLibraryParseDTO errorCodeDTO = ErrorReportLibraryUtil.parseAssertions(baseResult);
RequestResult result = errorCodeDTO.getResult();
report.setId(UUID.randomUUID().toString());
String resourceId = result.getResourceId();
report.setResourceId(resourceId);
report.setReportId(reportId);
report.setTotalAssertions(Long.parseLong(result.getTotalAssertions() + ""));
report.setPassAssertions(Long.parseLong(result.getPassAssertions() + ""));
report.setCreateTime(System.currentTimeMillis());
String status = result.getError() == 0 ? ExecuteResult.Success.name() : ExecuteResult.Error.name();
if (CollectionUtils.isNotEmpty(errorCodeDTO.getErrorCodeList())) {
status = ExecuteResult.errorReportResult.name();
report.setErrorCode(errorCodeDTO.getErrorCodeStr());
}
report.setStatus(status);
report.setRequestTime(result.getEndTime() - result.getStartTime());
//记录基础信息
//记录基础信息
private ApiScenarioReportBaseInfoDTO getBaseInfo(RequestResult result) {
ApiScenarioReportBaseInfoDTO baseInfoDTO = new ApiScenarioReportBaseInfoDTO();
baseInfoDTO.setReqName(result.getName());
baseInfoDTO.setReqSuccess(result.isSuccess());
@ -136,7 +127,27 @@ public class ApiScenarioReportResultService {
baseInfoDTO.setRspCode(result.getResponseResult().getResponseCode());
baseInfoDTO.setRspTime(result.getResponseResult().getResponseTime());
}
report.setBaseInfo(JSONObject.toJSONString(baseInfoDTO));
return baseInfoDTO;
}
private ApiScenarioReportResultWithBLOBs newApiScenarioReportResult(String reportId, RequestResult baseResult) {
//解析误报内容
ErrorReportLibraryParseDTO errorCodeDTO = ErrorReportLibraryUtil.parseAssertions(baseResult);
RequestResult result = errorCodeDTO.getResult();
String resourceId = result.getResourceId();
ApiScenarioReportResultWithBLOBs report = newScenarioReportResult(reportId, resourceId);
report.setTotalAssertions(Long.parseLong(result.getTotalAssertions() + ""));
report.setPassAssertions(Long.parseLong(result.getPassAssertions() + ""));
String status = result.getError() == 0 ? ExecuteResult.Success.name() : ExecuteResult.Error.name();
if (CollectionUtils.isNotEmpty(errorCodeDTO.getErrorCodeList())) {
status = ExecuteResult.errorReportResult.name();
report.setErrorCode(errorCodeDTO.getErrorCodeStr());
}
report.setStatus(status);
report.setRequestTime(result.getEndTime() - result.getStartTime());
report.setBaseInfo(JSONObject.toJSONString(getBaseInfo(result)));
report.setContent(JSON.toJSONString(result).getBytes(StandardCharsets.UTF_8));
return report;
}
@ -156,16 +167,7 @@ public class ApiScenarioReportResultService {
try {
RequestResult requestResult = JSON.parseObject(new String(baseResult.getContent(), StandardCharsets.UTF_8), RequestResult.class);
//记录基础信息
ApiScenarioReportBaseInfoDTO baseInfo = new ApiScenarioReportBaseInfoDTO();
baseInfo.setReqName(StringUtils.isEmpty(requestResult.getName()) ? "" : requestResult.getName());
baseInfo.setReqSuccess(requestResult.isSuccess());
baseInfo.setReqError(requestResult.getError());
baseInfo.setReqStartTime(requestResult.getStartTime());
if (requestResult.getResponseResult() != null) {
baseInfo.setRspCode(requestResult.getResponseResult().getResponseCode());
baseInfo.setRspTime(requestResult.getResponseResult().getResponseTime());
}
baseResult.setBaseInfo(JSONObject.toJSONString(baseInfo));
baseResult.setBaseInfo(JSONObject.toJSONString(getBaseInfo(requestResult)));
apiScenarioReportResultMapper.updateByPrimaryKeySelective(baseResult);
return baseResult;
} catch (Exception e) {

View File

@ -20,6 +20,7 @@ import io.metersphere.commons.utils.LogUtil;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.RequestResult;
import io.metersphere.utils.LoggerUtil;
import io.metersphere.commons.constants.CommandType;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
@ -176,6 +177,7 @@ public class ApiScenarioReportStructureService {
children.setAllIndex("" + (children.getIndex() == 0 ? (i + 1) : children.getIndex()));
children.setResourceId(resourceId + "_" + children.getAllIndex());
}
children.setCmdType(element.getString("commandType"));
dto.getChildren().add(children);
if (element.containsKey("hashTree") && !requests.contains(children.getType())) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
@ -307,7 +309,7 @@ public class ApiScenarioReportStructureService {
dto.setErrorCode(reportResults.get(0).getErrorCode());
}
}
if (StringUtils.isNotEmpty(dto.getType()) && requests.contains(dto.getType()) && dto.getValue() == null) {
if (StringUtils.isNotEmpty(dto.getType()) && requests.contains(dto.getType()) && dto.getValue() == null || isUiUnExecuteCommand(dto)) {
RequestResultExpandDTO requestResultExpandDTO = new RequestResultExpandDTO();
requestResultExpandDTO.setStatus("unexecute");
requestResultExpandDTO.setName(dto.getLabel());
@ -415,6 +417,14 @@ public class ApiScenarioReportStructureService {
}
}
private boolean isUiUnExecuteCommand(StepTreeDTO dto) {
if (dto.getType().equals("MsUiCommand") && dto.getValue() == null
&& (StringUtils.isBlank(dto.getCmdType()) || !dto.getCmdType().equalsIgnoreCase(CommandType.COMMAND_TYPE_COMBINATION))) {
return true;
}
return false;
}
private List<ApiDefinitionExecResultVo> formatApiReport(String reportId, List<StepTreeDTO> stepList) {
ApiDefinitionExecResultExample example = new ApiDefinitionExecResultExample();
example.createCriteria().andIntegratedReportIdEqualTo(reportId);

View File

@ -0,0 +1,12 @@
package io.metersphere.commons.constants;
/**
* atomic 原子指令前端 后端 一对一
* combine 前端指令包含了多个指令实现 比如 IF 指令if 指令必须有 start end
* proxy 前端指令使用了代理模式 比如前端选择等待元素指令实际上还有一个子类别具体选择waitForElement 还是 waitForEditable
*/
public class CommandType {
public static final String COMMAND_TYPE_ATOM = "atom";
public static final String COMMAND_TYPE_COMBINATION = "combination";
public static final String COMMAND_TYPE_PROXY = "proxy";
}

View File

@ -13,14 +13,19 @@
<div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane :label="$t('api_report.total')" name="total">
<ms-scenario-results :treeData="fullTreeNodes" :console="content.console"
v-on:requestResult="requestResult" ref="resultsTree"/>
<ms-scenario-results :treeData="fullTreeNodes"
:console="content.console"
:report="report"
v-on:requestResult="requestResult"
ref="resultsTree"/>
</el-tab-pane>
<el-tab-pane name="fail">
<template slot="label">
<span class="fail">{{ $t('api_report.fail') }}</span>
</template>
<ms-scenario-results v-on:requestResult="requestResult" :console="content.console"
<ms-scenario-results v-on:requestResult="requestResult"
:console="content.console"
:report="report"
:treeData="fullTreeNodes" ref="failsTree"
:errorReport="content.error"/>
</el-tab-pane>
@ -28,14 +33,18 @@
<template slot="label">
<span class="fail" style="color: #F6972A">{{ $t('error_report_library.option.name') }}</span>
</template>
<ms-scenario-results v-on:requestResult="requestResult" :console="content.console"
<ms-scenario-results v-on:requestResult="requestResult"
:report="report"
:console="content.console"
:treeData="fullTreeNodes" ref="errorReportTree"/>
</el-tab-pane>
<el-tab-pane name="unExecute" v-if="content.unExecute > 0">
<template slot="label">
<span class="fail" style="color: #9C9B9A">{{ $t('api_test.home_page.detail_card.unexecute') }}</span>
</template>
<ms-scenario-results v-on:requestResult="requestResult" :console="content.console"
<ms-scenario-results v-on:requestResult="requestResult"
:report="report"
:console="content.console"
:treeData="fullTreeNodes" ref="unExecuteTree"/>
</el-tab-pane>
<el-tab-pane name="console">

View File

@ -33,6 +33,7 @@ export default {
treeData: Array,
console: String,
errorReport: Number,
report: Object,
defaultExpand: {
default: false,
type: Boolean,

View File

@ -13,8 +13,8 @@
</el-col>
<el-col :span="3">
<span v-if="!isUnexecute" :style="!result.success ? 'color: #FE6F71' : ''">
{{ result.endTime - result.startTime }} ms
<span v-if="!isUnexecute" :style="result && !result.success ? 'color: #FE6F71' : ''">
{{ result.time }} ms
</span>
</el-col>
@ -26,8 +26,8 @@
v-if="!isUnexecute">
<el-image
style="width: 100px; height: 100px"
:src="'/resource/ui/get?fileName=' + result.url"
:preview-src-list="['/resource/ui/get?fileName=' + result.url]">
:src="'/resource/ui/get?fileName=' + result.uiImg"
:preview-src-list="['/resource/ui/get?fileName=' + result.uiImg]">
</el-image>
<el-button slot="reference" type="text">{{ $t('截图') }}</el-button>
</el-popover>
@ -38,7 +38,7 @@
<el-tag size="mini" v-if="isUnexecute">
{{ $t('api_test.home_page.detail_card.unexecute') }}
</el-tag>
<el-tag size="mini" type="success" v-else-if="result.success">
<el-tag size="mini" type="success" v-else-if="result && result.success">
{{ $t('api_report.success') }}
</el-tag>
<el-tooltip v-else :content="result.body" placement="top">
@ -70,7 +70,7 @@ export default {
return this.command.label;
},
isUnexecute() {
return this.result && this.result.status === 'unexecute';
return !this.result || this.result.status === 'unexecute';
}
},
data() {