This commit is contained in:
chenjianxing 2021-01-13 09:56:52 +08:00
commit 53c2d6f7fa
18 changed files with 292 additions and 110 deletions

View File

@ -325,22 +325,17 @@ public class ApiAutomationService {
}
/**
* 场景测试执行
* 生成HashTree
*
* @param request
* @return
* @param apiScenarios 场景
* @param request 请求参数
* @param isSave 是否需要生成报告
* @return hashTree
*/
public String run(RunScenarioRequest request) {
List<ApiScenarioWithBLOBs> apiScenarios = null;
List<String> ids = request.getScenarioIds();
if (request.isSelectAllDate()) {
ids = this.getAllScenarioIdsByFontedSelect(
request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds());
}
apiScenarios = extApiScenarioMapper.selectIds(ids);
private HashTree generateHashTree(List<ApiScenarioWithBLOBs> apiScenarios, RunScenarioRequest request, boolean isSave) {
HashTree jmeterHashTree = new ListedHashTree();
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = new ListedHashTree();
try {
boolean isFirst = true;
for (ApiScenarioWithBLOBs item : apiScenarios) {
@ -380,49 +375,44 @@ public class ApiAutomationService {
LinkedList<MsTestElement> scenarios = new LinkedList<>();
scenarios.add(scenario);
// 创建场景报告
createScenarioReport(group.getName(), item.getId(), item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
if (isSave) {
createScenarioReport(group.getName(), item.getId(), item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
}
group.setHashTree(scenarios);
testPlan.getHashTree().add(group);
}
} catch (Exception ex) {
MSException.throwException(ex.getMessage());
}
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
return jmeterHashTree;
}
/**
* 场景测试执行
*
* @param request
* @return
*/
public String run(RunScenarioRequest request) {
List<ApiScenarioWithBLOBs> apiScenarios = null;
List<String> ids = request.getScenarioIds();
if (request.isSelectAllDate()) {
ids = this.getAllScenarioIdsByFontedSelect(
request.getModuleIds(), request.getName(), request.getProjectId(), request.getFilters(), request.getUnSelectIds());
}
apiScenarios = extApiScenarioMapper.selectIds(ids);
String runMode = ApiRunMode.SCENARIO.name();
if (StringUtils.isNotBlank(request.getRunMode()) && StringUtils.equals(request.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
runMode = ApiRunMode.SCENARIO_PLAN.name();
}
// 调用执行方法
jMeterService.runDefinition(request.getId(), jmeterHashTree, request.getReportId(), runMode);
jMeterService.runDefinition(request.getId(), generateHashTree(apiScenarios, request, true), request.getReportId(), runMode);
return request.getId();
}
/**
* 获取前台查询条件查询的所有(未经分页筛选)数据ID
*
* @param moduleIds 模块ID_前台查询时所选择的
* @param name 搜索条件_名称_前台查询时所输入的
* @param projectId 所属项目_前台查询时所在项目
* @param filters 过滤集合__前台查询时的过滤条件
* @param unSelectIds 未勾选ID_前台没有勾选的ID
* @return
*/
private List<String> getAllScenarioIdsByFontedSelect(List<String> moduleIds, String name, String projectId, List<String> filters, List<String> unSelectIds) {
ApiScenarioRequest selectRequest = new ApiScenarioRequest();
selectRequest.setModuleIds(moduleIds);
selectRequest.setName(name);
selectRequest.setProjectId(projectId);
selectRequest.setFilters(filters);
selectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
List<ApiScenarioDTO> list = extApiScenarioMapper.list(selectRequest);
List<String> allIds = list.stream().map(ApiScenarioDTO::getId).collect(Collectors.toList());
List<String> ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList());
return ids;
}
/**
* 场景测试执行
*
@ -460,6 +450,29 @@ public class ApiAutomationService {
return dto;
}
/**
* 获取前台查询条件查询的所有(未经分页筛选)数据ID
*
* @param moduleIds 模块ID_前台查询时所选择的
* @param name 搜索条件_名称_前台查询时所输入的
* @param projectId 所属项目_前台查询时所在项目
* @param filters 过滤集合__前台查询时的过滤条件
* @param unSelectIds 未勾选ID_前台没有勾选的ID
* @return
*/
private List<String> getAllScenarioIdsByFontedSelect(List<String> moduleIds, String name, String projectId, List<String> filters, List<String> unSelectIds) {
ApiScenarioRequest selectRequest = new ApiScenarioRequest();
selectRequest.setModuleIds(moduleIds);
selectRequest.setName(name);
selectRequest.setProjectId(projectId);
selectRequest.setFilters(filters);
selectRequest.setWorkspaceId(SessionUtils.getCurrentWorkspaceId());
List<ApiScenarioDTO> list = extApiScenarioMapper.list(selectRequest);
List<String> allIds = list.stream().map(ApiScenarioDTO::getId).collect(Collectors.toList());
List<String> ids = allIds.stream().filter(id -> !unSelectIds.contains(id)).collect(Collectors.toList());
return ids;
}
public String addScenarioToPlan(SaveApiPlanRequest request) {
if (CollectionUtils.isEmpty(request.getPlanIds())) {
MSException.throwException(Translator.get("plan id is null "));
@ -578,51 +591,8 @@ public class ApiAutomationService {
apiScenarios = extApiScenarioMapper.selectIds(ids);
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = new ListedHashTree();
try {
boolean isFirst = true;
for (ApiScenarioWithBLOBs item : apiScenarios) {
if (item.getStepTotal() == 0) {
MSException.throwException(item.getName() + "" + Translator.get("automation_exec_info"));
break;
}
MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName());
group.setName(UUID.randomUUID().toString());
// 批量执行的结果直接存储为报告
if (isFirst) {
group.setName(request.getId());
isFirst = false;
}
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JSONObject element = JSON.parseObject(item.getScenarioDefinition());
MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
new TypeReference<LinkedList<MsTestElement>>() {
});
scenario.setHashTree(elements);
}
if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
scenario.setVariables(variables);
}
group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>();
scenarios.add(scenario);
group.setHashTree(scenarios);
testPlan.getHashTree().add(group);
}
} catch (Exception ex) {
MSException.throwException(ex.getMessage());
}
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
HashTree jmeterHashTree = generateHashTree(apiScenarios, request, false);
String jmx = testPlan.getJmx(jmeterHashTree);
String name = request.getName() + ".jmx";

View File

@ -6,6 +6,7 @@ import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.track.dto.TestCaseReportMetricDTO;
import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.dto.TestPlanLoadCaseDTO;
import org.apache.commons.lang3.StringUtils;
public abstract class ReportComponent {
@ -26,4 +27,7 @@ public abstract class ReportComponent {
public void readRecord(ApiScenarioDTO testCase) {
}
public void readRecord(TestPlanLoadCaseDTO testCase) {
}
}

View File

@ -4,10 +4,7 @@ import io.metersphere.api.dto.automation.ApiScenarioDTO;
import io.metersphere.api.dto.automation.ScenarioStatus;
import io.metersphere.api.dto.definition.TestPlanApiCaseDTO;
import io.metersphere.commons.constants.TestPlanTestCaseStatus;
import io.metersphere.track.dto.FailureTestCasesAdvanceDTO;
import io.metersphere.track.dto.TestCaseReportMetricDTO;
import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.dto.*;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
@ -17,6 +14,7 @@ public class ReportFailureAdvanceResultComponent extends ReportComponent {
private List<TestPlanCaseDTO> functionalTestCases = new ArrayList<>();
private List<TestPlanApiCaseDTO> apiTestCases = new ArrayList<>();
private List<ApiScenarioDTO> scenarioTestCases = new ArrayList<>();
private List<TestPlanLoadCaseDTO> loadTestCases = new ArrayList<>();
public ReportFailureAdvanceResultComponent(TestPlanDTO testPlan) {
super(testPlan);
@ -44,12 +42,20 @@ public class ReportFailureAdvanceResultComponent extends ReportComponent {
}
}
@Override
public void readRecord(TestPlanLoadCaseDTO testCase) {
if (StringUtils.equals(testCase.getCaseStatus(), "error")) {
this.loadTestCases.add(testCase);
}
}
@Override
public void afterBuild(TestCaseReportMetricDTO testCaseReportMetric) {
FailureTestCasesAdvanceDTO failureTestCasesAdvanceDTO = new FailureTestCasesAdvanceDTO();
failureTestCasesAdvanceDTO.setFunctionalTestCases(functionalTestCases);
failureTestCasesAdvanceDTO.setApiTestCases(apiTestCases);
failureTestCasesAdvanceDTO.setScenarioTestCases(scenarioTestCases);
failureTestCasesAdvanceDTO.setLoadTestCases(loadTestCases);
testCaseReportMetric.setFailureTestCases(failureTestCasesAdvanceDTO);
}
}

View File

@ -16,15 +16,19 @@ public class ReportResultAdvancedChartComponent extends ReportComponent {
Map<String, TestCaseReportStatusResultDTO> functionalStatusResultMap = new HashMap<>();
Map<String, TestCaseReportStatusResultDTO> apiStatusResultMap = new HashMap<>();
Map<String, TestCaseReportStatusResultDTO> scenarioStatusResultMap = new HashMap<>();
Map<String, TestCaseReportStatusResultDTO> loadStatusResultMap = new HashMap<>();
private static Map<String, String> apiResultMap = new HashMap<>();
private static Map<String, String> scenarioResultMap = new HashMap<>();
private static Map<String, String> loadResultMap = new HashMap<>();
static {
apiResultMap.put("success", TestPlanTestCaseStatus.Pass.name());
apiResultMap.put("error", TestPlanTestCaseStatus.Failure.name());
scenarioResultMap.put(ScenarioStatus.Success.name(), TestPlanTestCaseStatus.Pass.name());
scenarioResultMap.put(ScenarioStatus.Fail.name(), TestPlanTestCaseStatus.Failure.name());
loadResultMap.put("success", TestPlanTestCaseStatus.Pass.name());
loadResultMap.put("error", TestPlanTestCaseStatus.Failure.name());
}
public ReportResultAdvancedChartComponent(TestPlanDTO testPlan) {
@ -47,6 +51,11 @@ public class ReportResultAdvancedChartComponent extends ReportComponent {
getStatusResultMap(scenarioStatusResultMap, scenarioResultMap.get(testCase.getLastResult()));
}
@Override
public void readRecord(TestPlanLoadCaseDTO testCase) {
getStatusResultMap(loadStatusResultMap, loadResultMap.get(testCase.getCaseStatus()));
}
@Override
public void afterBuild(TestCaseReportMetricDTO testCaseReportMetric) {
testCaseReportMetric.setExecuteResult(getReportStatusResult());
@ -57,6 +66,7 @@ public class ReportResultAdvancedChartComponent extends ReportComponent {
buildFunctionalStatusResult(reportStatusResult);
buildApiStatusResult(reportStatusResult);
buildScenarioStatusResult(reportStatusResult);
buildLoadStatusResult(reportStatusResult);
return reportStatusResult;
}
@ -87,6 +97,14 @@ public class ReportResultAdvancedChartComponent extends ReportComponent {
reportStatusResult.setScenarioResult(scenarioStatusResult);
}
private void buildLoadStatusResult(TestCaseReportAdvanceStatusResultDTO reportStatusResult) {
List<TestCaseReportStatusResultDTO> loadStatusResult = new ArrayList<>();
addToReportStatusResultList(loadStatusResultMap, loadStatusResult, TestPlanTestCaseStatus.Pass.name());
addToReportStatusResultList(loadStatusResultMap, loadStatusResult, TestPlanTestCaseStatus.Failure.name());
addToReportStatusResultList(loadStatusResultMap, loadStatusResult, TestPlanTestCaseStatus.Underway.name());
reportStatusResult.setLoadResult(loadStatusResult);
}
private void addToReportStatusResultList(Map<String, TestCaseReportStatusResultDTO> resultMap, List<TestCaseReportStatusResultDTO> reportStatusResultList, String status) {
if (resultMap.get(status) != null) {
reportStatusResultList.add(resultMap.get(status));

View File

@ -13,4 +13,5 @@ public class FailureTestCasesAdvanceDTO {
private List<TestPlanCaseDTO> functionalTestCases;
private List<TestPlanApiCaseDTO> apiTestCases;
private List<ApiScenarioDTO> scenarioTestCases;
private List<TestPlanLoadCaseDTO> loadTestCases;
}

View File

@ -11,5 +11,6 @@ public class TestCaseReportAdvanceStatusResultDTO {
private List<TestCaseReportStatusResultDTO> functionalResult;
private List<TestCaseReportStatusResultDTO> apiResult;
private List<TestCaseReportStatusResultDTO> scenarioResult;
private List<TestCaseReportStatusResultDTO> loadResult;
}

View File

@ -26,13 +26,11 @@ import io.metersphere.notice.service.NoticeSendService;
import io.metersphere.service.SystemParameterService;
import io.metersphere.track.Factory.ReportComponentFactory;
import io.metersphere.track.domain.ReportComponent;
import io.metersphere.track.dto.TestCaseReportMetricDTO;
import io.metersphere.track.dto.TestPlanCaseDTO;
import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.dto.TestPlanDTOWithMetric;
import io.metersphere.track.dto.*;
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.AddTestPlanRequest;
import io.metersphere.track.request.testplan.LoadCaseRequest;
import io.metersphere.track.request.testplancase.QueryTestPlanCaseRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
@ -649,6 +647,7 @@ public class TestPlanService {
List<Issues> issues = buildFunctionalCaseReport(planId, components);
buildApiCaseReport(planId, components);
buildScenarioCaseReport(planId, components);
buildLoadCaseReport(planId, components);
TestCaseReportMetricDTO testCaseReportMetricDTO = new TestCaseReportMetricDTO();
components.forEach(component -> {
@ -680,6 +679,17 @@ public class TestPlanService {
}
}
public void buildLoadCaseReport(String planId, List<ReportComponent> components) {
LoadCaseRequest request = new LoadCaseRequest();
request.setTestPlanId(planId);
List<TestPlanLoadCaseDTO> loadDTOs = testPlanLoadCaseService.list(request);
for (TestPlanLoadCaseDTO item : loadDTOs) {
for (ReportComponent component : components) {
component.readRecord(item);
}
}
}
public List<Issues> buildFunctionalCaseReport(String planId, List<ReportComponent> components) {
IssuesService issuesService = (IssuesService) CommonBeanFactory.getBean("issuesService");
List<TestPlanCaseDTO> testPlanTestCases = listTestCaseByPlanId(planId);

View File

@ -13,7 +13,7 @@
<slot name="headerLeft">
<i class="icon el-icon-arrow-right" :class="{'is-active': request.active}"
@click="active(request)"/>
<el-input v-if="(isShowInput || !request.name) && !isDeletedOrRef" size="small" v-model="request.name" class="name-input"
<el-input draggable v-if="(isShowInput || !request.name) && !isDeletedOrRef" size="small" v-model="request.name" class="name-input"
@blur="isShowInput = false" :placeholder="$t('commons.input_name')"/>
<span v-else>
{{request.name}}

View File

@ -3,7 +3,7 @@
@copy="copyRow"
@remove="remove"
:data="jsr223ProcessorData"
:draggable="true"
:draggable="draggable"
color="#B8741A"
background-color="#F9F1EA"
:title="title">
@ -39,6 +39,7 @@
import MsInstructionsIcon from "../../../common/components/MsInstructionsIcon";
import MsDropdown from "../../../common/components/MsDropdown";
import ApiBaseComponent from "./common/ApiBaseComponent";
export default {
name: "MsJsr233Processor",
components: {ApiBaseComponent, MsDropdown, MsInstructionsIcon, MsCodeEdit},
@ -92,6 +93,10 @@
this.jsr223ProcessorData = this.jsr223Processor;
},
props: {
draggable: {
type: Boolean,
default: false,
},
isReadOnly: {
type: Boolean,
default:
@ -147,26 +152,33 @@
.ace_editor {
border-radius: 5px;
}
.script-content {
height: calc(100vh - 570px);
}
.script-index {
padding: 0 20px;
}
.template-title {
margin-bottom: 5px;
font-weight: bold;
font-size: 15px;
}
.document-url {
margin-top: 10px;
}
.instructions-icon {
margin-left: 5px;
}
.ms-dropdown {
margin-bottom: 20px;
}
/deep/ .el-divider {
margin-bottom: 10px;
}

View File

@ -10,6 +10,7 @@
:title="$t('api_test.automation.loop_controller')">
<template v-slot:headerLeft>
<i class="icon el-icon-arrow-right" :class="{'is-active': controller.active}" @click="active(controller)" style="margin-right: 10px"/>
<el-radio @change="changeRadio" class="ms-radio" v-model="controller.loopType" label="LOOP_COUNT">{{$t('loop.loops_title')}}</el-radio>
<el-radio @change="changeRadio" class="ms-radio" v-model="controller.loopType" label="FOREACH">{{$t('loop.foreach')}}</el-radio>
<el-radio @change="changeRadio" class="ms-radio" v-model="controller.loopType" label="WHILE">{{$t('loop.while')}}</el-radio>
@ -71,6 +72,7 @@
<script>
import ApiBaseComponent from "./common/ApiBaseComponent";
export default {
name: "MsLoopController",
components: {ApiBaseComponent},
@ -157,10 +159,15 @@
.ms-span {
margin: 10px;
}
.ms-radio {
color: #606266;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", Arial, sans-serif;
font-size: 13px;
font-weight: normal;
}
.icon.is-active {
transform: rotate(90deg);
}
</style>

View File

@ -72,9 +72,13 @@
<ms-jsr233-processor v-if="row.label ==='JSR223 PostProcessor'" @copyRow="copyRow" @remove="remove" :is-read-only="false" :title="$t('api_test.definition.request.post_script')" style-type="color: #783887;background-color: #F2ECF3"
:jsr223-processor="row"/>
<!--断言规则-->
<ms-api-assertions v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>
<div style="margin-top: 10px">
<ms-api-assertions v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>
</div>
<!--提取规则-->
<ms-api-extract :is-read-only="isReadOnly" @copyRow="copyRow" @remove="remove" v-if="row.type==='Extract'" :extract="row"/>
<div style="margin-top: 10px">
<ms-api-extract :is-read-only="isReadOnly" @copyRow="copyRow" @remove="remove" v-if="row.type==='Extract'" :extract="row"/>
</div>
</div>
</div>
</el-col>

View File

@ -50,9 +50,13 @@
<ms-jsr233-processor v-if="row.label ==='JSR223 PostProcessor'" @copyRow="copyRow" @remove="remove" :is-read-only="false" :title="$t('api_test.definition.request.post_script')" style-type="color: #783887;background-color: #F2ECF3"
:jsr223-processor="row"/>
<!--断言规则-->
<ms-api-assertions v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>
<div style="margin-top: 10px">
<ms-api-assertions v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>
</div>
<!--提取规则-->
<ms-api-extract :is-read-only="isReadOnly" @copyRow="copyRow" @remove="remove" v-if="row.type==='Extract'" :extract="row"/>
<div style="margin-top: 10px">
<ms-api-extract :is-read-only="isReadOnly" @copyRow="copyRow" @remove="remove" v-if="row.type==='Extract'" :extract="row"/>
</div>
</div>
</div>
</el-col>

View File

@ -76,9 +76,13 @@
<ms-jsr233-processor v-if="row.label ==='JSR223 PostProcessor'" @copyRow="copyRow" @remove="remove" :is-read-only="false" :title="$t('api_test.definition.request.post_script')"
:jsr223-processor="row"/>
<!--断言规则-->
<ms-api-assertions :response="response" v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>
<div style="margin-top: 10px">
<ms-api-assertions :response="response" v-if="row.type==='Assertions'" @copyRow="copyRow" @remove="remove" :is-read-only="isReadOnly" :assertions="row"/>
</div>
<!--提取规则-->
<ms-api-extract :response="response" :is-read-only="isReadOnly" @copyRow="copyRow" @remove="remove" v-if="row.type==='Extract'" :extract="row"/>
<div style="margin-top: 10px">
<ms-api-extract :response="response" :is-read-only="isReadOnly" @copyRow="copyRow" @remove="remove" v-if="row.type==='Extract'" :extract="row"/>
</div>
</div>
</div>
</el-col>

View File

@ -184,6 +184,7 @@ export default {
},
methods: {
initTable() {
console.log('init')
this.selectRows = new Set();
let param = {};
param.testPlanId = this.planId;
@ -198,7 +199,7 @@ export default {
},
refreshStatus() {
this.refreshScheduler = setInterval(() => {
let arr = this.tableData.filter(data => data.status !== 'Completed' && data.status !== 'Error');
let arr = this.tableData.filter(data => data.status !== 'Completed' && data.status !== 'Error' && data.status !== "Saved");
if (arr.length > 0) {
this.initTable();
} else {

View File

@ -4,6 +4,7 @@
<functional-failure-cases-list v-if="showFunctional" :functional-test-cases="failureTestCases.functionalTestCases"/>
<api-failure-cases-list v-if="showApi" :api-test-cases="failureTestCases.apiTestCases"/>
<scenario-failure-cases-list v-if="showScenario" :scenario-test-cases="failureTestCases.scenarioTestCases"/>
<load-failure-cases-list v-if="showLoad" :load-test-cases="failureTestCases.loadTestCases"/>
</common-component>
</template>
@ -18,13 +19,15 @@
import FunctionalFailureCasesList from "./component/FunctionalFailureCasesList";
import ApiFailureCasesList from "./component/ApiFailureCasesList";
import ScenarioFailureCasesList from "./component/ScenarioFailureCasesList";
import LoadFailureCasesList
from "@/business/components/track/plan/view/comonents/report/TemplateComponent/component/LoadFailureCasesList";
export default {
name: "FailureResultAdvanceComponent",
components: {
ScenarioFailureCasesList,
ApiFailureCasesList,
FunctionalFailureCasesList,
StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem, CommonComponent},
StatusTableItem, MethodTableItem, TypeTableItem, PriorityTableItem, CommonComponent, LoadFailureCasesList},
props: {
failureTestCases: {
type: Object,
@ -73,6 +76,15 @@
lastResult: "Failure",
updateTime: new Date(),
}
],
loadTestCases: [
{
caseName: 'testCase4',
projectName: 'P3',
userName: '/module1/module2',
createTime: new Date(),
status: 'error',
}
]
}
}
@ -80,14 +92,18 @@
},
computed: {
showFunctional() {
return this.failureTestCases.functionalTestCases.length > 0 || (this.failureTestCases.apiTestCases.length <= 0 && this.failureTestCases.scenarioTestCases.length <= 0);
return this.failureTestCases.functionalTestCases.length > 0
|| (this.failureTestCases.apiTestCases.length <= 0 && this.failureTestCases.scenarioTestCases.length <= 0 && this.failureTestCases.loadTestCases.length <= 0);
},
showApi() {
return this.failureTestCases.apiTestCases.length > 0;
},
showScenario() {
return this.failureTestCases.scenarioTestCases.length > 0;
}
},
showLoad() {
return this.failureTestCases.loadTestCases.length > 0;
},
},
methods: {
goFailureTestCase(row) {

View File

@ -17,6 +17,11 @@
<ms-pie-chart v-if="isShow" :text="'场景测试用例'"
:name="$t('test_track.plan_view.test_result')" :data="scenarioCharData"/>
</div>
<div class="char-item" v-if="showLoad">
<ms-pie-chart v-if="isShow" :text="'性能测试用例'"
:name="$t('test_track.plan_view.test_result')" :data="loadCharData"/>
</div>
</div>
</common-component>
@ -43,6 +48,7 @@
functionalCharData: [],
apiCharData: [],
scenarioCharData: [],
loadCharData: [],
isShow: true
}
},
@ -69,19 +75,28 @@
{status: 'Failure', count: '350'},
{status: 'Underway', count: '110'},
],
loadResult: [
{status: 'Pass', count: '205'},
{status: 'Failure', count: '350'},
{status: 'Underway', count: '110'},
],
}
}
}
},
computed: {
showFunctional() {
return this.executeResult.functionalResult.length > 0 || (this.executeResult.apiResult.length <= 0 && this.executeResult.scenarioResult.length <= 0);
return this.executeResult.functionalResult.length > 0
|| (this.executeResult.apiResult.length <= 0 && this.executeResult.scenarioResult.length <= 0 && this.executeResult.loadResult.length <= 0);
},
showApi() {
return this.executeResult.apiResult.length > 0;
},
showScenario() {
return this.executeResult.scenarioResult.length > 0;
},
showLoad() {
return this.executeResult.loadResult.length > 0;
}
},
watch: {
@ -97,6 +112,7 @@
this.getFunctionalCharData();
this.getApiCharData();
this.getScenarioCharData();
this.getLoadCharData();
this.reload();
},
getFunctionalCharData() {
@ -129,6 +145,16 @@
});
}
},
getLoadCharData() {
this.loadCharData = [];
if (this.executeResult.loadResult) {
this.executeResult.loadResult.forEach(item => {
let data = this.dataMap.get(item.status);
data.value = item.count;
this.loadCharData.push(data);
});
}
},
reload() {
this.isShow = false;
this.$nextTick(function () {

View File

@ -0,0 +1,96 @@
<template>
<div class="failure-cases-list">
<div class="failure-cases-list-header">
性能测试用例
</div>
<el-table
row-key="id"
@row-click="goFailureTestCase"
:data="loadTestCases">
<el-table-column
prop="caseName"
:label="$t('commons.name')"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="projectName"
:label="$t('load_test.project_name')"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="userName"
:label="$t('load_test.user_name')"
show-overflow-tooltip>
</el-table-column>
<el-table-column
sortable
prop="createTime"
:label="$t('commons.create_time')">
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
prop="status"
column-key="status"
:filters="statusFilters"
:label="$t('commons.status')">
<template v-slot:default="{row}">
<ms-performance-test-status :row="row"/>
</template>
</el-table-column>
<!-- <el-table-column-->
<!-- prop="caseStatus"-->
<!-- :label="$t('test_track.plan.load_case.execution_status')">-->
<!-- <template v-slot:default="{row}">-->
<!-- <el-tag size="mini" type="danger" v-if="row.caseStatus === 'error'">-->
<!-- {{ row.caseStatus }}-->
<!-- </el-tag>-->
<!-- <el-tag size="mini" type="success" v-else-if="row.caseStatus === 'success'">-->
<!-- {{ row.caseStatus }}-->
<!-- </el-tag>-->
<!-- <span v-else>-</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
</el-table>
</div>
</template>
<script>
import MsTag from "@/business/components/common/components/MsTag";
import PriorityTableItem from "@/business/components/track/common/tableItems/planview/PriorityTableItem";
import TypeTableItem from "@/business/components/track/common/tableItems/planview/TypeTableItem";
import MethodTableItem from "@/business/components/track/common/tableItems/planview/MethodTableItem";
import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem";
import MsPerformanceTestStatus from "@/business/components/performance/test/PerformanceTestStatus";
export default {
name: "LoadFailureCasesList",
components: {MsTag, PriorityTableItem, TypeTableItem, MethodTableItem, StatusTableItem, MsPerformanceTestStatus},
props: ['loadTestCases'],
data() {
return {
statusFilters: [
{text: 'Saved', value: 'Saved'},
{text: 'Starting', value: 'Starting'},
{text: 'Running', value: 'Running'},
{text: 'Reporting', value: 'Reporting'},
{text: 'Completed', value: 'Completed'},
{text: 'Error', value: 'Error'}
],
}
},
methods: {
goFailureTestCase(row) {
this.$emit("openFailureTestCase", row);
}
}
}
</script>
<style scoped>
</style>

View File

@ -205,11 +205,13 @@ export default {
if (this.reportId) {
this.result = this.$get("/performance/report/" + this.reportId, res => {
let data = res.data;
this.status = data.status;
this.$set(this.report, "id", this.reportId);
this.$set(this.report, "status", data.status);
if (this.status === "Completed") {
this.initReportTimeInfo();
if (data) {
this.status = data.status;
this.$set(this.report, "id", this.reportId);
this.$set(this.report, "status", data.status);
if (this.status === "Completed") {
this.initReportTimeInfo();
}
}
});
}