Merge remote-tracking branch 'origin/master'

This commit is contained in:
wenyann 2021-01-27 16:51:12 +08:00
commit 97a99f8006
19 changed files with 130 additions and 48 deletions

View File

@ -343,13 +343,41 @@ public class ApiScenarioReportService {
ids = allIds.stream().filter(id -> !reportRequest.getUnSelectIds().contains(id)).collect(Collectors.toList());
}
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
detailExample.createCriteria().andReportIdIn(ids);
apiScenarioReportDetailMapper.deleteByExample(detailExample);
//为预防数量太多调用删除方法时引起SQL过长的Bug此处采取分批执行的方式
//每次处理的数据数量
int handleCount = 7000;
//每次处理的集合
List<String> handleIdList = new ArrayList<>(handleCount);
while (ids.size() > handleCount){
handleIdList = new ArrayList<>(handleCount);
List<String> otherIdList = new ArrayList<>();
for (int index = 0;index < ids.size();index++){
if(index<handleCount){
handleIdList.add(ids.get(index));
}else{
otherIdList.add(ids.get(index));
}
}
//处理本次的数据
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
detailExample.createCriteria().andReportIdIn(handleIdList);
apiScenarioReportDetailMapper.deleteByExample(detailExample);
ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample();
apiTestReportExample.createCriteria().andIdIn(handleIdList);
apiScenarioReportMapper.deleteByExample(apiTestReportExample);
//转存剩余的数据
ids = otherIdList;
}
ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample();
apiTestReportExample.createCriteria().andIdIn(ids);
apiScenarioReportMapper.deleteByExample(apiTestReportExample);
//处理最后剩余的数据
if(!ids.isEmpty()){
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
detailExample.createCriteria().andReportIdIn(ids);
apiScenarioReportDetailMapper.deleteByExample(detailExample);
ApiScenarioReportExample apiTestReportExample = new ApiScenarioReportExample();
apiTestReportExample.createCriteria().andIdIn(ids);
apiScenarioReportMapper.deleteByExample(apiTestReportExample);
}
}
public long countByProjectID(String projectId) {

View File

@ -219,7 +219,8 @@
</if>
<if test="request.name != null">
and (api_definition.name like CONCAT('%', #{request.name},'%')
or api_definition.tags like CONCAT('%', #{request.name},'%'))
or api_definition.tags like CONCAT('%', #{request.name},'%')
or api_definition.num like CONCAT('%', #{request.name},'%'))
</if>
<if test="request.protocol != null">
AND api_definition.protocol = #{request.protocol}

View File

@ -143,7 +143,9 @@
</if>
<if test="request.name != null">
and (api_scenario.name like CONCAT('%', #{request.name},'%') or api_scenario.tags like CONCAT('%', #{request.name},'%'))
and (api_scenario.name like CONCAT('%', #{request.name},'%')
or api_scenario.tags like CONCAT('%', #{request.name},'%')
or api_scenario.num like CONCAT('%', #{request.name},'%'))
</if>
<if test="request.workspaceId != null">
AND project.workspace_id = #{request.workspaceId}

View File

@ -284,7 +284,9 @@
</foreach>
</if>
<if test="request.name != null and request.name!=''">
and (t1.name like CONCAT('%', #{request.name},'%') or t1.tags like CONCAT('%', #{request.name},'%'))
and (t1.name like CONCAT('%', #{request.name},'%')
or t1.tags like CONCAT('%', #{request.name},'%')
or t1.num like CONCAT('%', #{request.name},'%'))
</if>
<if test="request.createTime > 0">
and t1.create_time >= #{request.createTime}

View File

@ -122,7 +122,7 @@
<select id="list" resultType="io.metersphere.track.dto.TestPlanCaseDTO">
select test_plan_test_case.id as id, test_case.id as caseId, test_case.name, test_case.priority,
test_case.type,test_case.test_id as testId,test_case.node_id,
test_case.type,test_case.test_id as testId,test_case.node_id, test_case.tags,
test_case.node_path, test_case.method, test_case.num, test_plan_test_case.executor, test_plan_test_case.status,
test_plan_test_case.update_time, test_case_node.name as model, project.name as projectName,
test_plan_test_case.plan_id as planId
@ -139,7 +139,7 @@
</if>
<if test="request.name != null">
and (test_case.name like CONCAT('%', #{request.name},'%') or test_case.num like
CONCAT('%',#{request.name},'%'))
CONCAT('%',#{request.name},'%') or test_case.tags like CONCAT('%', #{request.name},'%'))
</if>
<if test="request.id != null">
and test_case.id = #{request.id}

View File

@ -105,25 +105,27 @@ public class TestPlanTestJob extends MsScheduleJob {
//需要更新这里来保证PlanCase的状态能正常更改
apiTestCaseService.run(blobs,UUID.randomUUID().toString(),testPlanReport.getId(),this.resourceId,ApiRunMode.SCHEDULE_API_PLAN.name());
}
LogUtil.info("-------------- testplan schedule ---------- api case over -----------------");
//执行场景执行任务
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
String senarionReportID = UUID.randomUUID().toString();
scenarioRequest.setId(senarionReportID);
scenarioRequest.setReportId(senarionReportID);
scenarioRequest.setProjectId(projectID);
scenarioRequest.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
scenarioRequest.setExecuteType(ExecuteType.Saved.name());
Map<String, Map<String,String>> testPlanScenarioIdMap = new HashMap<>();
testPlanScenarioIdMap.put(resourceId, this.planScenarioIdMap);
scenarioRequest.setTestPlanScenarioIDMap(testPlanScenarioIdMap);
scenarioRequest.setReportUserID(this.userId);
scenarioRequest.setTestPlanID(this.resourceId);
scenarioRequest.setRunMode(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name());
scenarioRequest.setTestPlanReportId(testPlanReport.getId());
testPlanService.runScenarioCase(scenarioRequest);
LogUtil.info("-------------- testplan schedule ---------- scenario case over -----------------");
//执行场景执行任务
if(!planScenarioIdMap.isEmpty()){
LogUtil.info("-------------- testplan schedule ---------- api case over -----------------");
SchedulePlanScenarioExecuteRequest scenarioRequest = new SchedulePlanScenarioExecuteRequest();
String senarionReportID = UUID.randomUUID().toString();
scenarioRequest.setId(senarionReportID);
scenarioRequest.setReportId(senarionReportID);
scenarioRequest.setProjectId(projectID);
scenarioRequest.setTriggerMode(ReportTriggerMode.SCHEDULE.name());
scenarioRequest.setExecuteType(ExecuteType.Saved.name());
Map<String, Map<String,String>> testPlanScenarioIdMap = new HashMap<>();
testPlanScenarioIdMap.put(resourceId, this.planScenarioIdMap);
scenarioRequest.setTestPlanScenarioIDMap(testPlanScenarioIdMap);
scenarioRequest.setReportUserID(this.userId);
scenarioRequest.setTestPlanID(this.resourceId);
scenarioRequest.setRunMode(ApiRunMode.SCHEDULE_SCENARIO_PLAN.name());
scenarioRequest.setTestPlanReportId(testPlanReport.getId());
testPlanService.runScenarioCase(scenarioRequest);
LogUtil.info("-------------- testplan schedule ---------- scenario case over -----------------");
}
//执行性能测试任务
List<String> performaneReportIDList = new ArrayList<>();
for (Map.Entry<String,String> entry: this.performanceIdMap.entrySet()) {

View File

@ -115,6 +115,7 @@ public class TestPlanApiCaseService {
TestPlanApiCase apiCase = new TestPlanApiCase();
apiCase.setId(id);
apiCase.setStatus(status);
apiCase.setUpdateTime(System.currentTimeMillis());
testPlanApiCaseMapper.updateByPrimaryKeySelective(apiCase);
}

View File

@ -281,6 +281,18 @@ public class TestPlanReportService {
component.afterBuild(testCaseReportMetricDTO);
});
if (StringUtils.equals(ReportTriggerMode.SCHEDULE.name(),triggerMode)
&&StringUtils.equals(resourceRunMode, ApiRunMode.SCHEDULE_PERFORMANCE_TEST.name())) {
//如果是性能测试作为触发由于延迟原因可能会出现报告已经结束但是状态还是进行中的状态
List<TestCaseReportStatusResultDTO> loadResult = testCaseReportMetricDTO.getExecuteResult().getLoadResult();
for (TestCaseReportStatusResultDTO dto: loadResult) {
if(StringUtils.equals(dto.getStatus(),TestPlanTestCaseStatus.Underway.name())){
dto.setStatus(TestPlanTestCaseStatus.Pass.name());
}
}
testCaseReportMetricDTO.getExecuteResult().setLoadResult(loadResult);
}
TestPlanReportDataExample example = new TestPlanReportDataExample();
example.createCriteria().andTestPlanReportIdEqualTo(planReportId);
List<TestPlanReportDataWithBLOBs> testPlanReportDataList = testPlanReportDataMapper.selectByExampleWithBLOBs(example);
@ -437,7 +449,7 @@ public class TestPlanReportService {
if(loadTestReportFromDatabase == null){
//检查错误数据
if(errorDataCheckMap.containsKey(loadTestReportId)){
if(errorDataCheckMap.get(loadTestReportId)>20){
if(errorDataCheckMap.get(loadTestReportId)>10){
performaneReportIDList.remove(loadTestReportId);
}else {
errorDataCheckMap.put(loadTestReportId,errorDataCheckMap.get(loadTestReportId)+1);

View File

@ -97,6 +97,7 @@
renderComponent: true,
isHide: true,
activeName: 'default',
redirectFlag: 'none',
currentModule: null,
moduleOptions: [],
tabs: [],
@ -150,6 +151,15 @@
},
changeRedirectParam(redirectIDParam) {
this.redirectID = redirectIDParam;
if(redirectIDParam!=null){
if(this.redirectFlag == "none"){
this.activeName = "default";
this.addListener();
this.redirectFlag = "redirected";
}
}else{
this.redirectFlag = "none";
}
},
addTab(tab) {
if (!getCurrentProjectID()) {

View File

@ -3,7 +3,7 @@
<el-card class="table-card" v-loading="loading">
<template v-slot:header>
<ms-table-header :condition.sync="condition" @search="selectByParam" title=""
:show-create="false"/>
:show-create="false" :tip="$t('commons.search_by_id_name_tag')"/>
</template>
<el-table ref="scenarioTable" border :data="tableData" class="adjust-table ms-select-all-fixed"

View File

@ -212,7 +212,8 @@
this.$emit('singleRun', data);
},
copyCase(data) {
let obj = {name: "copy_" + data.name, priority: data.priority, active: true, request: data.request};
let uuid = getUUID();
let obj = {name: "copy_" + data.name, priority: data.priority, active: true, request: data.request, uuid: uuid};
this.$emit('copyCase', obj);
},
selectTestCase(item, $event) {

View File

@ -20,7 +20,7 @@
<el-container v-loading="result.loading">
<el-main>
<div v-for="(item,index) in apiCaseList" :key="index">
<div v-for="(item,index) in apiCaseList" :key="item.id ? item.id : item.uuid">
<api-case-item v-loading="singleLoading && singleRunId === item.id || batchLoadingIds.indexOf(item.id) > -1"
@refresh="refresh"
@singleRun="singleRun"
@ -243,7 +243,8 @@
if (!request.hashTree) {
request.hashTree = [];
}
let obj = {apiDefinitionId: this.api.id, name: '', priority: 'P0', active: true, tags: []};
let uuid = getUUID();
let obj = {apiDefinitionId: this.api.id, name: '', priority: 'P0', active: true, tags: [], uuid: uuid};
obj.request = request;
this.apiCaseList.unshift(obj);
}

View File

@ -5,7 +5,7 @@
@isApiListEnableChange="isApiListEnableChange">
<el-link type="primary" style="float:right;margin-top: 5px" @click="open">{{$t('commons.adv_search.title')}}</el-link>
<el-input placeholder="搜索" @blur="search" @keyup.enter.native="search" class="search-input" size="small"
<el-input :placeholder="$t('commons.search_by_id_name_tag')" @blur="search" @keyup.enter.native="search" class="search-input" size="small"
v-model="condition.name"/>
<el-table v-loading="result.loading"

View File

@ -5,7 +5,7 @@
@isApiListEnableChange="isApiListEnableChange">
<el-link type="primary" @click="open" style="float: right;margin-top: 5px">{{$t('commons.adv_search.title')}}</el-link>
<el-input :placeholder="$t('api_monitor.please_search')" @blur="search" class="search-input" size="small" @keyup.enter.native="search"
<el-input :placeholder="$t('commons.search_by_id_name_tag')" @blur="search" class="search-input" size="small" @keyup.enter.native="search"
v-model="condition.name"/>
<el-table v-loading="result.loading"

View File

@ -15,6 +15,7 @@
:filter-node-method="filterNode"
:expand-on-click-node="false"
highlight-current
style="overflow: auto"
@node-click="nodeClick"
ref="tree"
>

View File

@ -76,6 +76,14 @@
</template>
</el-table-column>
<el-table-column prop="tags" :label="$t('commons.tag')">
<template v-slot:default="scope">
<div v-for="(tag, index) in scope.row.showTags" :key="tag + '_' + index">
<ms-tag type="success" effect="plain" :content="tag"/>
</div>
</template>
</el-table-column>
<el-table-column
prop="method"
:filters="methodFilters"
@ -179,8 +187,9 @@
</template>
</el-table-column>
<el-table-column
min-width="100"
:label="$t('commons.operating')">
fixed="right"
min-width="100"
:label="$t('commons.operating')">
<template v-slot:default="scope">
<ms-table-operator-button :is-tester-permission="true" :tip="$t('commons.edit')" icon="el-icon-edit"
@exec="handleEdit(scope.row)"/>
@ -231,6 +240,7 @@ import ShowMoreBtn from "../../../../case/components/ShowMoreBtn";
import BatchEdit from "../../../../case/components/BatchEdit";
import ClassicEditor from "@ckeditor/ckeditor5-build-classic";
import {hub} from "@/business/components/track/plan/event-bus";
import MsTag from "@/business/components/common/components/MsTag";
export default {
name: "FunctionalTestCaseList",
@ -243,7 +253,7 @@ export default {
StatusTableItem,
PriorityTableItem, StatusEdit, ExecutorEdit, MsTipButton, MsTablePagination,
MsTableHeader, NodeBreadcrumb, MsTableButton, ShowMoreBtn,
BatchEdit
BatchEdit, MsTag
},
data() {
return {
@ -257,7 +267,7 @@ export default {
currentPage: 1,
pageSize: 10,
total: 0,
status:'default',
status: 'default',
selectRows: new Set(),
testPlan: {},
isReadOnly: false,
@ -319,7 +329,7 @@ export default {
planId: {
type: String
},
clickType:String,
clickType: String,
selectNodeIds: {
type: Array
},
@ -354,10 +364,10 @@ export default {
// param.planId = this.planId;
this.condition.planId = this.planId;
}
if(this.clickType){
if(this.status =='default'){
if (this.clickType) {
if (this.status == 'default') {
this.condition.status = this.clickType;
}else{
} else {
this.condition.status = null;
}
this.status = 'all';
@ -373,6 +383,7 @@ export default {
this.tableData = data.listObject;
for (let i = 0; i < this.tableData.length; i++) {
if (this.tableData[i]) {
this.$set(this.tableData[i], "showTags", JSON.parse(this.tableData[i].tags));
this.$set(this.tableData[i], "issuesSize", 0);
this.$get("/issues/get/" + this.tableData[i].caseId).then(response => {
let issues = response.data.data;
@ -381,7 +392,11 @@ export default {
this.$set(this.tableData[i], "issuesContent", issues);
}
}).catch(() => {
this.$set(this.tableData[i], "issuesContent", [{title: '获取缺陷失败',description: '获取缺陷失败',platform: '获取缺陷失败' }]);
this.$set(this.tableData[i], "issuesContent", [{
title: '获取缺陷失败',
description: '获取缺陷失败',
platform: '获取缺陷失败'
}]);
})
}
}
@ -597,4 +612,7 @@ export default {
cursor: pointer;
}
.el-tag {
margin-left: 10px;
}
</style>

View File

@ -150,7 +150,8 @@ export default {
name: "Trigger Mode",
manual: "Manual trigger",
schedule: "Scheduled Task",
api: "API call"
api: "API call",
case: "Case"
},
adv_search: {
title: 'Advanced Search',

View File

@ -151,7 +151,8 @@ export default {
name: "触发方式",
manual: "手动触发",
schedule: "定时任务",
api: "API调用"
api: "API调用",
case: "用例触发"
},
adv_search: {
title: '高级搜索',

View File

@ -151,7 +151,8 @@ export default {
name: "觸發方式",
manual: "手動觸發",
schedule: "定時任務",
api: "API調用"
api: "API調用",
case: "用例觸發"
},
adv_search: {
title: '高級搜索',