fix(功能回退): 误报库功能回退

误报库功能回退
This commit is contained in:
song-tianyang 2022-01-04 10:35:43 +08:00 committed by fit2-zhao
parent 6f99bdea77
commit 7c775562f3
13 changed files with 305 additions and 514 deletions

View File

@ -1,6 +1,5 @@
package io.metersphere.api.dto.scenario;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.api.dto.scenario.environment.GlobalScriptConfig;
@ -30,8 +29,6 @@ public class HttpConfig {
private MsJSR223PostProcessor postProcessor;
private GlobalScriptConfig globalScriptConfig;
private ApiModuleMapper apiModuleMapper;
private List<MsAssertions> assertions;
private List<MsAssertions> errorReportAssertions;
private String description;

View File

@ -1,7 +1,6 @@
package io.metersphere.api.dto.scenario.environment;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.definition.request.assertions.MsAssertions;
import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
@ -31,8 +30,6 @@ public class EnvironmentConfig {
//全局前后置脚本都配置
private GlobalScriptConfig globalScriptConfig;
private JSONObject authManager;
private List<MsAssertions> assertions;
private boolean useErrorCode;
public EnvironmentConfig() {
this.commonConfig = new CommonConfig();

View File

@ -1,11 +1,8 @@
package io.metersphere.api.service;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.ErrorReportLibraryParseDTO;
import io.metersphere.base.domain.ApiScenarioReportResult;
import io.metersphere.base.mapper.ApiScenarioReportResultMapper;
import io.metersphere.commons.constants.ExecuteResult;
import io.metersphere.commons.utils.ErrorReportLibraryUtil;
import io.metersphere.dto.RequestResult;
import io.metersphere.utils.LoggerUtil;
import org.apache.commons.collections.CollectionUtils;
@ -39,8 +36,6 @@ public class ApiScenarioReportResultService {
private ApiScenarioReportResult newApiScenarioReportResult(String reportId, RequestResult result) {
ApiScenarioReportResult report = new ApiScenarioReportResult();
//解析误报内容
ErrorReportLibraryParseDTO errorCodeDTO = ErrorReportLibraryUtil.parseAssertions(result);
report.setId(UUID.randomUUID().toString());
result.setEndTime(System.currentTimeMillis());
if (result.getResponseResult() != null) {
@ -60,12 +55,7 @@ public class ApiScenarioReportResultService {
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.errorCode.name();
report.setErrorCode(errorCodeDTO.getErrorCodeStr());
}
report.setStatus(status);
report.setStatus(result.getError() == 0 ? "Success" : "Error");
report.setRequestTime(result.getEndTime() - result.getStartTime());
report.setContent(JSON.toJSONString(result).getBytes(StandardCharsets.UTF_8));
return report;

View File

@ -110,34 +110,27 @@ public class ApiScenarioReportStructureService {
}
}
private void scenarioCalculate(List<StepTreeDTO> dtoList, AtomicLong isError, AtomicLong isErrorReport) {
private void scenarioCalculate(List<StepTreeDTO> dtoList, AtomicLong isError) {
for (StepTreeDTO step : dtoList) {
if(step.getValue() != null && StringUtils.isNotEmpty(step.getErrorCode())){
isErrorReport.set(isErrorReport.longValue() + 1);
break;
}else if (step.getValue() != null && step.getValue().getError() > 0) {
if (step.getValue() != null && step.getValue().getError() > 0) {
isError.set(isError.longValue() + 1);
break;
} else if (CollectionUtils.isNotEmpty(step.getChildren())) {
scenarioCalculate(step.getChildren(), isError,isErrorReport);
scenarioCalculate(step.getChildren(), isError);
}
}
}
private void calculate(List<StepTreeDTO> dtoList, AtomicLong totalScenario, AtomicLong scenarioError, AtomicLong totalTime,AtomicLong errorReport) {
private void calculate(List<StepTreeDTO> dtoList, AtomicLong totalScenario, AtomicLong scenarioError, AtomicLong totalTime) {
for (StepTreeDTO step : dtoList) {
if (StringUtils.equals(step.getType(), "scenario")) {
totalScenario.set((totalScenario.longValue() + 1));
// 失败结果数量
AtomicLong error = new AtomicLong();
AtomicLong errorCode = new AtomicLong();
scenarioCalculate(step.getChildren(), error,errorCode);
scenarioCalculate(step.getChildren(), error);
if (error.longValue() > 0) {
scenarioError.set((scenarioError.longValue() + 1));
}
if (errorCode.longValue() > 0) {
errorReport.set((errorReport.longValue() + 1));
}
} else if (step.getValue() != null) {
if (step.getValue().getStartTime() == 0 || step.getValue().getEndTime() == 0) {
totalTime.set(totalTime.longValue() + 0);
@ -146,23 +139,19 @@ public class ApiScenarioReportStructureService {
}
}
if (CollectionUtils.isNotEmpty(step.getChildren())) {
calculate(step.getChildren(), totalScenario, scenarioError, totalTime,errorReport);
calculate(step.getChildren(), totalScenario, scenarioError, totalTime);
}
}
}
private void calculateStep(List<StepTreeDTO> dtoList, AtomicLong stepError, AtomicLong stepTotal,AtomicLong stepErrorCode) {
private void calculateStep(List<StepTreeDTO> dtoList, AtomicLong stepError, AtomicLong stepTotal) {
for (StepTreeDTO step : dtoList) {
// 失败结果数量
AtomicLong error = new AtomicLong();
AtomicLong errorReport = new AtomicLong();
scenarioCalculate(step.getChildren(), error,errorReport);
scenarioCalculate(step.getChildren(), error);
if (error.longValue() > 0) {
stepError.set((stepError.longValue() + 1));
}
if (errorReport.longValue() > 0) {
stepErrorCode.set((stepErrorCode.longValue() + 1));
}
if (CollectionUtils.isNotEmpty(step.getChildren())) {
stepTotal.set((stepTotal.longValue() + step.getChildren().size()));
}
@ -179,35 +168,19 @@ public class ApiScenarioReportStructureService {
for (int i = 0; i < reportResults.size(); i++) {
if (i == 0) {
dto.setValue(JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class));
dto.setErrorCode(reportResults.get(0).getErrorCode());
} else {
StepTreeDTO step = new StepTreeDTO(dto.getLabel(), UUID.randomUUID().toString(), dto.getType(), (i + 1));
step.setValue(JSON.parseObject(new String(reportResults.get(i).getContent(), StandardCharsets.UTF_8), RequestResult.class));
step.setErrorCode(reportResults.get(i).getErrorCode());
dtoList.add(step);
}
}
} else {
String content = new String(reportResults.get(0).getContent(), StandardCharsets.UTF_8);
dto.setValue(JSON.parseObject(content, RequestResult.class));
dto.setErrorCode(reportResults.get(0).getErrorCode());
}
}
if (CollectionUtils.isNotEmpty(dto.getChildren())) {
reportFormatting(dto.getChildren(), maps);
if(StringUtils.isEmpty(dto.getErrorCode())){
//统计child的errorCode
List<String> childErrorCodeList = new ArrayList<>();
for (StepTreeDTO child : dto.getChildren()) {
if(StringUtils.isNotEmpty(child.getErrorCode()) && !childErrorCodeList.contains(child.getErrorCode())){
childErrorCodeList.add(child.getErrorCode());
}
}
if(CollectionUtils.isNotEmpty(childErrorCodeList)){
dto.setErrorCode(StringUtils.join(childErrorCodeList,","));
}
}
}
}
// 循环步骤请求从新排序
@ -235,38 +208,40 @@ public class ApiScenarioReportStructureService {
if (CollectionUtils.isNotEmpty(reportStructureWithBLOBs) && CollectionUtils.isNotEmpty(reportResults)) {
reportDTO.setTotal(reportResults.size());
reportDTO.setError(reportResults.stream().filter(e -> StringUtils.equals(e.getStatus(), "Error")).collect(Collectors.toList()).size());
reportDTO.setErrorCode(reportResults.stream().filter(e -> StringUtils.isNotEmpty(e.getErrorCode())).collect(Collectors.toList()).size());
reportDTO.setPassAssertions(reportResults.stream().mapToLong(ApiScenarioReportResult::getPassAssertions).sum());
reportDTO.setTotalAssertions(reportResults.stream().mapToLong(ApiScenarioReportResult::getTotalAssertions).sum());
ApiScenarioReportStructureWithBLOBs scenarioReportStructure = reportStructureWithBLOBs.get(0);
List<StepTreeDTO> stepList = JSONArray.parseArray(new String(scenarioReportStructure.getResourceTree(), StandardCharsets.UTF_8), StepTreeDTO.class);
// 匹配结果
Map<String, List<ApiScenarioReportResult>> maps = reportResults.stream().collect(Collectors.groupingBy(ApiScenarioReportResult::getResourceId));
this.reportFormatting(stepList, maps);
// 统计场景数据
// 统计场景和步骤成功失败总量
AtomicLong totalScenario = new AtomicLong();
AtomicLong scenarioError = new AtomicLong();
AtomicLong totalTime = new AtomicLong();
AtomicLong errorReport = new AtomicLong();
calculate(stepList, totalScenario, scenarioError, totalTime,errorReport);
calculate(stepList, totalScenario, scenarioError, totalTime);
reportDTO.setTotalTime(totalTime.longValue());
reportDTO.setScenarioTotal(totalScenario.longValue());
reportDTO.setScenarioError(scenarioError.longValue());
reportDTO.setScenarioErrorReport(errorReport.longValue());
reportDTO.setScenarioSuccess((totalScenario.longValue() - scenarioError.longValue() -errorReport.longValue()));
//统计步骤数据
reportDTO.setScenarioSuccess((totalScenario.longValue() - scenarioError.longValue()));
AtomicLong stepError = new AtomicLong();
AtomicLong stepErrorCode = new AtomicLong();
AtomicLong stepTotal = new AtomicLong();
calculateStep(stepList, stepError, stepTotal,stepErrorCode);
calculateStep(stepList, stepError, stepTotal);
reportDTO.setScenarioStepTotal(stepTotal.longValue());
reportDTO.setScenarioStepError(stepError.longValue());
reportDTO.setScenarioStepErrorReport(stepErrorCode.longValue());
reportDTO.setScenarioStepSuccess((stepList.size() - stepError.longValue() - stepErrorCode.longValue()));
reportDTO.setScenarioStepSuccess((stepList.size() - stepError.longValue()));
reportDTO.setConsole(scenarioReportStructure.getConsole());
reportDTO.setSteps(stepList);
}
return reportDTO;
}
}

View File

@ -27,8 +27,6 @@ public class ApiDefinitionExecResult implements Serializable {
private String triggerMode;
private String versionId;
private String errorCode;
private String content;

View File

@ -844,76 +844,6 @@ public class ApiDefinitionExecResultExample {
return (Criteria) this;
}
public Criteria andVersionIdIsNull() {
addCriterion("version_id is null");
return (Criteria) this;
}
public Criteria andVersionIdIsNotNull() {
addCriterion("version_id is not null");
return (Criteria) this;
}
public Criteria andVersionIdEqualTo(String value) {
addCriterion("version_id =", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdNotEqualTo(String value) {
addCriterion("version_id <>", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdGreaterThan(String value) {
addCriterion("version_id >", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdGreaterThanOrEqualTo(String value) {
addCriterion("version_id >=", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdLessThan(String value) {
addCriterion("version_id <", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdLessThanOrEqualTo(String value) {
addCriterion("version_id <=", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdLike(String value) {
addCriterion("version_id like", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdNotLike(String value) {
addCriterion("version_id not like", value, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdIn(List<String> values) {
addCriterion("version_id in", values, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdNotIn(List<String> values) {
addCriterion("version_id not in", values, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdBetween(String value1, String value2) {
addCriterion("version_id between", value1, value2, "versionId");
return (Criteria) this;
}
public Criteria andVersionIdNotBetween(String value1, String value2) {
addCriterion("version_id not between", value1, value2, "versionId");
return (Criteria) this;
}
public Criteria andErrorCodeIsNull() {
addCriterion("error_code is null");
return (Criteria) this;

View File

@ -13,7 +13,6 @@
<result column="type" jdbcType="VARCHAR" property="type" />
<result column="actuator" jdbcType="VARCHAR" property="actuator" />
<result column="trigger_mode" jdbcType="VARCHAR" property="triggerMode" />
<result column="version_id" jdbcType="VARCHAR" property="versionId" />
<result column="error_code" jdbcType="VARCHAR" property="errorCode" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.ApiDefinitionExecResult">
@ -79,7 +78,7 @@
</sql>
<sql id="Base_Column_List">
id, `name`, resource_id, `status`, user_id, start_time, end_time, create_time, `type`,
actuator, trigger_mode, version_id, error_code
actuator, trigger_mode, error_code
</sql>
<sql id="Blob_Column_List">
content
@ -136,13 +135,13 @@
insert into api_definition_exec_result (id, `name`, resource_id,
`status`, user_id, start_time,
end_time, create_time, `type`,
actuator, trigger_mode, version_id,
error_code, content)
actuator, trigger_mode, error_code,
content)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR},
#{status,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR}, #{startTime,jdbcType=BIGINT},
#{endTime,jdbcType=BIGINT}, #{createTime,jdbcType=BIGINT}, #{type,jdbcType=VARCHAR},
#{actuator,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}, #{versionId,jdbcType=VARCHAR},
#{errorCode,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARCHAR})
#{actuator,jdbcType=VARCHAR}, #{triggerMode,jdbcType=VARCHAR}, #{errorCode,jdbcType=VARCHAR},
#{content,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.ApiDefinitionExecResult">
insert into api_definition_exec_result
@ -180,9 +179,6 @@
<if test="triggerMode != null">
trigger_mode,
</if>
<if test="versionId != null">
version_id,
</if>
<if test="errorCode != null">
error_code,
</if>
@ -224,9 +220,6 @@
<if test="triggerMode != null">
#{triggerMode,jdbcType=VARCHAR},
</if>
<if test="versionId != null">
#{versionId,jdbcType=VARCHAR},
</if>
<if test="errorCode != null">
#{errorCode,jdbcType=VARCHAR},
</if>
@ -277,9 +270,6 @@
<if test="record.triggerMode != null">
trigger_mode = #{record.triggerMode,jdbcType=VARCHAR},
</if>
<if test="record.versionId != null">
version_id = #{record.versionId,jdbcType=VARCHAR},
</if>
<if test="record.errorCode != null">
error_code = #{record.errorCode,jdbcType=VARCHAR},
</if>
@ -304,7 +294,6 @@
`type` = #{record.type,jdbcType=VARCHAR},
actuator = #{record.actuator,jdbcType=VARCHAR},
trigger_mode = #{record.triggerMode,jdbcType=VARCHAR},
version_id = #{record.versionId,jdbcType=VARCHAR},
error_code = #{record.errorCode,jdbcType=VARCHAR},
content = #{record.content,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
@ -324,7 +313,6 @@
`type` = #{record.type,jdbcType=VARCHAR},
actuator = #{record.actuator,jdbcType=VARCHAR},
trigger_mode = #{record.triggerMode,jdbcType=VARCHAR},
version_id = #{record.versionId,jdbcType=VARCHAR},
error_code = #{record.errorCode,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -363,9 +351,6 @@
<if test="triggerMode != null">
trigger_mode = #{triggerMode,jdbcType=VARCHAR},
</if>
<if test="versionId != null">
version_id = #{versionId,jdbcType=VARCHAR},
</if>
<if test="errorCode != null">
error_code = #{errorCode,jdbcType=VARCHAR},
</if>
@ -387,7 +372,6 @@
`type` = #{type,jdbcType=VARCHAR},
actuator = #{actuator,jdbcType=VARCHAR},
trigger_mode = #{triggerMode,jdbcType=VARCHAR},
version_id = #{versionId,jdbcType=VARCHAR},
error_code = #{errorCode,jdbcType=VARCHAR},
content = #{content,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
@ -404,7 +388,6 @@
`type` = #{type,jdbcType=VARCHAR},
actuator = #{actuator,jdbcType=VARCHAR},
trigger_mode = #{triggerMode,jdbcType=VARCHAR},
version_id = #{versionId,jdbcType=VARCHAR},
error_code = #{errorCode,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>

View File

@ -3,30 +3,25 @@
<ms-main-container>
<el-card>
<section class="report-container" v-if="this.report.testId">
<ms-api-report-view-header :show-cancel-button="showCancelButton" :is-plan="isPlan" :is-template="isTemplate"
:debug="debug" :report="report" @reportExport="handleExport"
@reportSave="handleSave"/>
<ms-api-report-view-header :show-cancel-button="showCancelButton" :is-plan="isPlan" :is-template="isTemplate" :debug="debug" :report="report" @reportExport="handleExport" @reportSave="handleSave"/>
<main v-if="isNotRunning">
<ms-metric-chart :content="content" :totalTime="totalTime"/>
<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" 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"
:treeData="fullTreeNodes" ref="failsTree"/>
<ms-scenario-results v-on:requestResult="requestResult" :console="content.console" :treeData="fullTreeNodes" ref="failsTree"/>
</el-tab-pane>
<el-tab-pane name="console">
<template slot="label">
<span class="console">{{ $t('api_test.definition.request.console') }}</span>
</template>
<ms-code-edit :mode="'text'" :read-only="true" :data.sync="content.console"
height="calc(100vh - 500px)"/>
<ms-code-edit :mode="'text'" :read-only="true" :data.sync="content.console" height="calc(100vh - 500px)"/>
</el-tab-pane>
</el-tabs>
@ -339,7 +334,7 @@ export default {
this.fullTreeNodes = report.steps;
this.content.console = report.console;
this.content.error = report.error;
this.content.success = (report.total - report.error - report.errorCode);
this.content.success = (report.total - report.error);
this.totalTime = report.totalTime;
}
this.loading = false;

View File

@ -277,11 +277,10 @@ export default {
this.content = {scenarios: []};
}
this.content.error = this.content.error;
this.content.success = (this.content.total - this.content.error - this.content.errorCode);
this.content.success = (this.content.total - this.content.error);
this.totalTime = this.content.totalTime;
this.fullTreeNodes = this.content.steps;
this.fullTreeNodes = JSON.parse(JSON.stringify(this.fullTreeNodes));
this.recursiveSorting(this.fullTreeNodes);
console.info(this.fullTreeNodes);
this.reload();
}
});

View File

@ -19,81 +19,64 @@
</div>
<ms-chart id="chart" ref="chart" :options="options" :height="220" :autoresize="true" v-else/>
<el-row type="flex" justify="center" align="middle">
<div>
<div class="metric-icon-box" style="height: 26px">
<span class="ms-point-success" style="margin: 7px"/>
<div class="metric-box">
<div class="value">{{ content.success }} {{ $t('api_report.success') }}</div>
</div>
</div>
<el-divider></el-divider>
<div class="metric-icon-box" style="height: 26px">
<span class="ms-point-error" style="margin: 7px"/>
<div class="metric-box">
<div class="value">{{ content.error }} {{ $t('api_report.fail') }}</div>
</div>
</div>
<el-divider v-if="content.errorCode > 0"></el-divider>
<div class="metric-icon-box" style="height: 26px">
<span class="ms-point-error-code" v-if="content.errorCode > 0" style="margin: 7px"/>
<div class="metric-box" v-if="content.errorCode > 0">
<div class="value">{{ content.errorCode }} {{ $t('error_report_library.option.name') }}</div>
</div>
</div>
<span class="ms-point-success"/>
<div class="metric-box">
<div class="value">{{ content.success }}</div>
<div class="name">{{ $t('api_report.success') }}</div>
</div>
<span class="ms-point-error"/>
<div class="metric-box">
<div class="value">{{ content.error }}</div>
<div class="name">{{ $t('api_report.fail') }}</div>
</div>
</el-row>
</el-row>
</div>
<div class="split"></div>
<!-- 场景统计 -->
<div style="width: 50%">
<el-row type="flex" justify="center" align="middle">
<!-- <div class="metric-box" style="margin-right: 50px">-->
<div class="metric-box">
<div class="value">{{ content.scenarioTotal ? content.scenarioTotal : 0}}</div>
<div class="name">{{ $t('api_test.scenario.scenario') }}</div>
</div>
<!-- <i class="circle success" style="margin-left: 20px;margin-right: 20px"/>-->
<span class="ms-point-success"/>
<div class="metric-box">
<div class="value">{{ content.scenarioSuccess ? content.scenarioSuccess: 0 }}</div>
<div class="name">{{ $t('api_report.success') }}</div>
</div>
<!-- <div style="width: 40px"></div>-->
<!-- <i class="circle fail" style="margin-left: 20px;margin-right: 20px"/>-->
<span class="ms-point-error"/>
<div class="metric-box">
<div class="value">{{ content.scenarioError ? content.scenarioError : 0 }}</div>
<div class="name">{{ $t('api_report.fail') }}</div>
</div>
</el-row>
<el-divider></el-divider>
<el-row type="flex" justify="center" align="middle">
<el-row type="flex" justify="center" align="middle">
<div class="metric-box">
<div class="value">{{ content.scenarioTotal ? content.scenarioTotal : 0}}</div>
<div class="name">{{ $t('api_test.scenario.scenario') }}</div>
<div class="value">{{ content.scenarioStepTotal ? content.scenarioStepTotal : 0}}</div>
<div class="name">{{ $t('test_track.plan_view.step') }}</div>
</div>
<span class="ms-point-success"/>
<!-- <i class="circle success" style="margin-left: 20px;margin-right: 20px"/>-->
<div class="metric-box">
<div class="value">{{ content.scenarioSuccess ? content.scenarioSuccess: 0 }}</div>
<div class="value">{{ content.scenarioStepSuccess ? content.scenarioStepSuccess: 0 }}</div>
<div class="name">{{ $t('api_report.success') }}</div>
</div>
<!-- <div style="width: 40px"></div>-->
<!-- <i class="circle fail" style="margin-left: 20px;margin-right: 20px"/>-->
<span class="ms-point-error"/>
<div class="metric-box">
<div class="value">{{ content.scenarioError ? content.scenarioError : 0 }}</div>
<div class="value">{{ content.scenarioStepError ? content.scenarioStepError : 0 }}</div>
<div class="name">{{ $t('api_report.fail') }}</div>
</div>
<span class="ms-point-error-code" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 "/>
<div class="metric-box" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 ">
<div class="value">{{ content.scenarioErrorReport ? content.scenarioErrorReport : 0 }}</div>
<div class="name">{{ $t('error_report_library.option.name') }}</div>
</div>
</el-row>
<el-divider></el-divider>
<el-row type="flex" justify="center" align="middle">
<el-row type="flex" justify="center" align="middle">
<div class="metric-box">
<div class="value">{{ content.scenarioStepTotal ? content.scenarioStepTotal : 0}}</div>
<div class="name">{{ $t('test_track.plan_view.step') }}</div>
</div>
<span class="ms-point-success"/>
<div class="metric-box">
<div class="value">{{ content.scenarioStepSuccess ? content.scenarioStepSuccess: 0 }}</div>
<div class="name">{{ $t('api_report.success') }}</div>
</div>
<span class="ms-point-error"/>
<div class="metric-box">
<div class="value">{{ content.scenarioStepError ? content.scenarioStepError : 0 }}</div>
<div class="name">{{ $t('api_report.fail') }}</div>
</div>
<span class="ms-point-error-code" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 "/>
<div class="metric-box" v-if="content.scenarioErrorReport > 0 || content.scenarioStepErrorReport > 0 ">
<div class="value">{{ content.scenarioStepErrorReport ? content.scenarioStepErrorReport : 0 }}</div>
<div class="name">{{ $t('error_report_library.option.name') }}</div>
</div>
</el-row>
</el-row>
</el-row>
</div>
<div class="split"></div>
@ -109,11 +92,6 @@
<div class="value">{{ assertions }}</div>
<div class="name">{{ $t('api_report.assertions_pass') }}</div>
</div>
<div class="metric-icon-box" v-if="content.errorCode > 0">
<i class="el-icon-document-checked assertions"></i>
<div class="value">{{ errorCodeAssertions }}</div>
<div class="name">{{ $t('error_report_library.assertion') }}</div>
</div>
<div class="metric-icon-box">
<i class="el-icon-document-copy total"></i>
<div class="value">{{ this.content.total }}</div>
@ -126,270 +104,255 @@
</template>
<script>
import MsChart from "@/business/components/common/chart/MsChart";
import MsChart from "@/business/components/common/chart/MsChart";
export default {
name: "MsMetricChart",
components: {MsChart},
props: {
content: Object,
totalTime: Number,
isExport:{
type: Boolean,
default: false,
}
},
data() {
return {
hour: 0,
minutes: 0,
seconds: 0,
time: 0,
scenarioTotal: 0,
scenarioSuccess: 0,
scenarioError: 0,
reqTotal: 0,
}
},
created() {
this.initTime();
},
methods: {
initTime() {
this.time = this.totalTime;
this.seconds = (this.time) / 1000;
if (this.seconds >= 1) {
if (this.seconds < 60) {
this.seconds = Math.round(this.seconds * 100 / 1) / 100;
this.time = this.seconds + "s"
}
if (this.seconds > 60) {
this.minutes = Math.round(this.seconds / 60)
this.seconds = Math.round(this.seconds * 100 % 60) / 100;
this.time = this.minutes + "min" + this.seconds + "s"
}
if (this.minutes > 60) {
this.hour = Math.round(this.minutes / 60)
this.minutes = Math.round(this.minutes % 60)
this.time = this.hour + "hour" + this.minutes + "min" + this.seconds + "s"
}
} else {
this.time = this.totalTime + "ms"
export default {
name: "MsMetricChart",
components: {MsChart},
props: {
content: Object,
totalTime: Number,
isExport:{
type: Boolean,
default: false,
}
},
data() {
return {
hour: 0,
minutes: 0,
seconds: 0,
time: 0,
scenarioTotal: 0,
scenarioSuccess: 0,
scenarioError: 0,
reqTotal: 0,
}
},
created() {
this.initTime();
},
methods: {
initTime() {
this.time = this.totalTime;
this.seconds = (this.time) / 1000;
if (this.seconds >= 1) {
if (this.seconds < 60) {
this.seconds = Math.round(this.seconds * 100 / 1) / 100;
this.time = this.seconds + "s"
}
},
if (this.seconds > 60) {
this.minutes = Math.round(this.seconds / 60)
this.seconds = Math.round(this.seconds * 100 % 60) / 100;
this.time = this.minutes + "min" + this.seconds + "s"
}
if (this.minutes > 60) {
this.hour = Math.round(this.minutes / 60)
this.minutes = Math.round(this.minutes % 60)
this.time = this.hour + "hour" + this.minutes + "min" + this.seconds + "s"
}
} else {
this.time = this.totalTime + "ms"
}
},
computed: {
options() {
return {
color: ['#67C23A', '#F56C6C' ,'#F6972A'],
tooltip: {
trigger: 'item',
formatter: '{b}: {c} ({d}%)'
},
title: [{
text: this.content.total,
subtext: this.$t('api_report.request'),
top: 'center',
left: 'center',
textStyle: {
rich: {
align: 'center',
value: {
fontSize: 32,
fontWeight: 'bold',
padding: [10, 0]
},
name: {
fontSize: 14,
fontWeight: 'normal',
color: '#7F7F7F',
}
},
computed: {
options() {
return {
color: ['#67C23A', '#F56C6C'],
tooltip: {
trigger: 'item',
formatter: '{b}: {c} ({d}%)'
},
title: [{
text: this.content.total,
subtext: this.$t('api_report.request'),
top: 'center',
left: 'center',
textStyle: {
rich: {
align: 'center',
value: {
fontSize: 32,
fontWeight: 'bold',
padding: [10, 0]
},
name: {
fontSize: 14,
fontWeight: 'normal',
color: '#7F7F7F',
}
}
}],
series: [
{
type: 'pie',
radius: ['80%', '90%'],
avoidLabelOverlap: false,
hoverAnimation: false,
itemStyle: {
borderColor: "#FFF",
shadowColor: '#E1E1E1',
shadowBlur: 10
},
labelLine: {
show: false
},
data: [
{value: this.content.success},
{value: this.content.error},
{value: this.content.errorCode},
]
}
]
};
},
fail() {
return (this.content.error / this.content.total * 100).toFixed(0) + "%";
},
assertions() {
return this.content.passAssertions + " / " + this.content.totalAssertions;
},
errorCodeAssertions() {
return this.content.errorCode + " / " + this.content.totalAssertions;
}
}
}],
series: [
{
type: 'pie',
radius: ['80%', '90%'],
avoidLabelOverlap: false,
hoverAnimation: false,
itemStyle: {
borderColor: "#FFF",
shadowColor: '#E1E1E1',
shadowBlur: 10
},
labelLine: {
show: false
},
data: [
{value: this.content.success},
{value: this.content.error},
]
}
]
};
},
}
fail() {
return (this.content.error / this.content.total * 100).toFixed(0) + "%";
},
assertions() {
return this.content.passAssertions + " / " + this.content.totalAssertions;
}
},
}
</script>
<style scoped>
.metric-container {
padding: 5px 10px;
}
.metric-container {
padding: 5px 10px;
}
.metric-container #chart {
width: 140px;
height: 140px;
margin-right: 40px;
}
.metric-container #chart {
width: 140px;
height: 140px;
margin-right: 40px;
}
.metric-container .split {
margin: 20px;
height: 100px;
border-left: 1px solid #D8DBE1;
}
.metric-container .split {
margin: 20px;
height: 100px;
border-left: 1px solid #D8DBE1;
}
.metric-container .circle {
width: 12px;
height: 12px;
border-radius: 50%;
box-shadow: 0 0 20px 1px rgba(200, 216, 226, .42);
display: inline-block;
margin-right: 10px;
vertical-align: middle;
}
.metric-container .circle {
width: 12px;
height: 12px;
border-radius: 50%;
box-shadow: 0 0 20px 1px rgba(200, 216, 226, .42);
display: inline-block;
margin-right: 10px;
vertical-align: middle;
}
.metric-container .circle.success {
background-color: #67C23A;
}
.metric-container .circle.success {
background-color: #67C23A;
}
.metric-container .circle.fail {
background-color: #F56C6C;
}
.metric-container .circle.fail {
background-color: #F56C6C;
}
.metric-box {
display: inline-block;
text-align: center;
}
.metric-box {
display: inline-block;
text-align: center;
}
.metric-box .value {
font-size: 32px;
font-weight: 600;
letter-spacing: -.5px;
}
.metric-box .value {
font-size: 32px;
font-weight: 600;
letter-spacing: -.5px;
}
.metric-time .value {
font-size: 25px;
font-weight: 400;
letter-spacing: -.5px;
}
.metric-time .value {
font-size: 25px;
font-weight: 400;
letter-spacing: -.5px;
}
.metric-box .name {
font-size: 16px;
letter-spacing: -.2px;
color: #404040;
}
.metric-box .name {
font-size: 16px;
letter-spacing: -.2px;
color: #404040;
}
.metric-icon-box {
text-align: center;
margin: 0 10px;
}
.metric-icon-box {
text-align: center;
margin: 0 10px;
}
.metric-icon-box .value {
font-size: 20px;
font-weight: 600;
letter-spacing: -.4px;
line-height: 28px;
vertical-align: middle;
}
.metric-icon-box .value {
font-size: 20px;
font-weight: 600;
letter-spacing: -.4px;
line-height: 28px;
vertical-align: middle;
}
.metric-icon-box .name {
font-size: 13px;
letter-spacing: 1px;
color: #BFBFBF;
line-height: 18px;
}
.metric-icon-box .name {
font-size: 13px;
letter-spacing: 1px;
color: #BFBFBF;
line-height: 18px;
}
.metric-icon-box .fail {
color: #F56C6C;
font-size: 40px;
}
.metric-icon-box .fail {
color: #F56C6C;
font-size: 40px;
}
.metric-icon-box .assertions {
font-size: 40px;
}
.metric-icon-box .assertions {
font-size: 40px;
}
.metric-icon-box .total {
font-size: 40px;
}
.metric-icon-box .total {
font-size: 40px;
}
.ms-req {
border-radius: 50%;
height: 110px;
width: 110px;
display: inline-block;
vertical-align: top;
margin-right: 30px;
}
.ms-req {
border-radius: 50%;
height: 110px;
width: 110px;
display: inline-block;
vertical-align: top;
margin-right: 30px;
}
.ms-req-error {
border: 5px #F56C6C solid;
}
.ms-req-error {
border: 5px #F56C6C solid;
}
.ms-req-success {
border: 5px #67C23A solid;
}
.ms-req-success {
border: 5px #67C23A solid;
}
.ms-req-span {
display: block;
color: black;
height: 110px;
line-height: 110px;
text-align: center;
}
.ms-point-success {
border-radius: 50%;
height: 12px;
width: 12px;
display: inline-block;
vertical-align: top;
margin-left: 20px;
margin-right: 20px;
background-color : #67C23A;
}
.ms-req-span {
display: block;
color: black;
height: 110px;
line-height: 110px;
text-align: center;
}
.ms-point-success {
border-radius: 50%;
height: 12px;
width: 12px;
display: inline-block;
vertical-align: top;
margin-left: 20px;
margin-right: 20px;
background-color : #67C23A;
}
.ms-point-error {
border-radius: 50%;
height: 12px;
width: 12px;
display: inline-block;
vertical-align: top;
margin-left: 20px;
margin-right: 20px;
background-color : #F56C6C;
}
.ms-point-error-code {
border-radius: 50%;
height: 12px;
width: 12px;
display: inline-block;
vertical-align: top;
margin-left: 20px;
margin-right: 20px;
background-color : #F6972A;
}
.ms-point-error {
border-radius: 50%;
height: 12px;
width: 12px;
display: inline-block;
vertical-align: top;
margin-left: 20px;
margin-right: 20px;
background-color : #F56C6C;
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<el-card class="ms-cards" v-if="request && request.responseResult">
<div class="request-result">
<div @click="active">
<div @click="active" >
<el-row :gutter="10" type="flex" align="middle" class="info">
<el-col :span="10" v-if="indexNumber!=undefined">
<el-tooltip :content="getName(request.name)" placement="top">
@ -14,19 +14,8 @@
</div>
</el-tooltip>
</el-col>
<el-col :span="3">
<el-tooltip effect="dark" v-if="errorCode" :content="errorCode"
style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom"
:open-delay="800">
<div style="color: #F6972A">
{{ errorCode }}
</div>
</el-tooltip>
</el-col>
<el-col :span="6">
<el-tooltip effect="dark" :content="request.responseResult.responseCode"
style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom"
:open-delay="800">
<el-col :span="9">
<el-tooltip effect="dark" :content="request.responseResult.responseCode" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" placement="bottom" :open-delay="800">
<div style="color: #5daf34" v-if="request.success">
{{ request.responseResult.responseCode }}
</div>
@ -49,13 +38,7 @@
<i class="el-icon-loading" style="font-size: 16px"/>
{{ $t('commons.testing') }}
</el-tag>
<el-tag v-if="errorCode" class="ms-test-running" size="mini">
{{ $t('error_report_library.option.name') }}
</el-tag>
<el-tag size="mini" v-else-if="request.unexecute">{{
$t('api_test.home_page.detail_card.unexecute')
}}
</el-tag>
<el-tag size="mini" v-else-if="request.unexecute">{{ $t('api_test.home_page.detail_card.unexecute') }}</el-tag>
<el-tag size="mini" type="success" v-else-if="request.success"> {{ $t('api_report.success') }}</el-tag>
<el-tag size="mini" type="danger" v-else> {{ $t('api_report.fail') }}</el-tag>
</div>
@ -66,11 +49,11 @@
<el-collapse-transition>
<div v-show="isActive && !request.unexecute" style="width: 99%">
<ms-request-result-tail
:scenario-name="scenarioName"
:request-type="requestType"
:request="request"
:console="console"
v-if="isActive"/>
:scenario-name="scenarioName"
:request-type="requestType"
:request="request"
:console="console"
v-if="isActive"/>
</div>
</el-collapse-transition>
</div>
@ -98,7 +81,6 @@ export default {
scenarioName: String,
indexNumber: Number,
console: String,
errorCode: String,
},
data() {
return {
@ -118,8 +100,6 @@ export default {
},
}
},
created() {
},
methods: {
active() {
if (this.request.unexecute) {

View File

@ -9,7 +9,7 @@
</el-card>
</div>
<div v-else>
<ms-request-result :request="node.value" :indexNumber="node.index" :error-code="node.errorCode"
<ms-request-result :request="node.value" :indexNumber="node.index"
v-on:requestResult="requestResult"
:scenarioName="node.label" :console="console"/>
</div>

View File

@ -61,22 +61,6 @@
</el-tooltip>
<ms-api-auth-config :is-read-only="isReadOnly" :request="environment.config.authManager"/>
</el-tab-pane>
<!-- 全局断言-->
<el-tab-pane :label="$t('env_options.all_assertions')" name="assertions">
<el-row type="flex" :gutter="20">
<el-col :span="12">
<el-form-item
:label="$t('error_report_library.use_error_report')"
prop="status">
<el-switch v-model="environment.config.useErrorCode" style="margin-right: 10px"/>
{{$t('error_report_library.use_desc')}}
</el-form-item>
</el-col>
</el-row>
<global-assertions
:assertions="environment.config.assertions"/>
</el-tab-pane>
</el-tabs>
<div class="environment-footer">
<ms-dialog-footer