feat(测试计划): UI支持环境运行
--story=1010692 --user=张大海 【UI测试】支持与环境管理打通 https://www.tapd.cn/55049933/s/1315234
This commit is contained in:
parent
9d0388175a
commit
9e0bb8c208
|
@ -65,8 +65,6 @@ import org.springframework.kafka.core.KafkaTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Propagation;
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
|
@ -1550,6 +1548,10 @@ public class TestPlanService {
|
||||||
envMap = planTestPlanApiCaseService.getApiCaseEnv(planId);
|
envMap = planTestPlanApiCaseService.getApiCaseEnv(planId);
|
||||||
Map<String, List<String>> scenarioEnv = planTestPlanScenarioCaseService.getApiScenarioEnv(planId);
|
Map<String, List<String>> scenarioEnv = planTestPlanScenarioCaseService.getApiScenarioEnv(planId);
|
||||||
|
|
||||||
|
if (DiscoveryUtil.hasService(MicroServiceName.UI_TEST)) {
|
||||||
|
scenarioEnv = mergeUiScenarioEnv(planId, scenarioEnv);
|
||||||
|
}
|
||||||
|
|
||||||
Set<String> projectIds = scenarioEnv.keySet();
|
Set<String> projectIds = scenarioEnv.keySet();
|
||||||
for (String projectId : projectIds) {
|
for (String projectId : projectIds) {
|
||||||
if (envMap.containsKey(projectId)) {
|
if (envMap.containsKey(projectId)) {
|
||||||
|
@ -1572,6 +1574,32 @@ public class TestPlanService {
|
||||||
return envMap;
|
return envMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 合并ui场景的环境信息
|
||||||
|
* @param planId
|
||||||
|
* @param scenarioEnv
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<String, List<String>> mergeUiScenarioEnv(String planId, Map<String, List<String>> scenarioEnv) {
|
||||||
|
Map<String, List<String>> uiScenarioEnv = planTestPlanUiScenarioCaseService.getUiScenarioEnv(planId);
|
||||||
|
if (MapUtils.isEmpty(scenarioEnv)) {
|
||||||
|
return uiScenarioEnv;
|
||||||
|
}
|
||||||
|
if (MapUtils.isNotEmpty(uiScenarioEnv)) {
|
||||||
|
uiScenarioEnv.entrySet().forEach(entry -> {
|
||||||
|
if (scenarioEnv.containsKey(entry.getKey())) {
|
||||||
|
List<String> environmentIds = scenarioEnv.get(entry.getKey());
|
||||||
|
entry.getValue().forEach(eId -> {
|
||||||
|
if (!environmentIds.contains(eId)) {
|
||||||
|
environmentIds.add(eId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return scenarioEnv;
|
||||||
|
}
|
||||||
|
|
||||||
public String runPlan(TestPlanRunRequest testplanRunRequest) {
|
public String runPlan(TestPlanRunRequest testplanRunRequest) {
|
||||||
//检查测试计划下有没有可以执行的用例;
|
//检查测试计划下有没有可以执行的用例;
|
||||||
if (!haveExecCase(testplanRunRequest.getTestPlanId(), false)) {
|
if (!haveExecCase(testplanRunRequest.getTestPlanId(), false)) {
|
||||||
|
|
|
@ -153,4 +153,8 @@ public class PlanTestPlanUiScenarioCaseService extends UiTestService {
|
||||||
public List<UiScenarioReportWithBLOBs> selectExtForPlanReport(String planId) {
|
public List<UiScenarioReportWithBLOBs> selectExtForPlanReport(String planId) {
|
||||||
return microService.getForDataArray(serviceName, BASE_URL + "/get/report/ext/" + planId, UiScenarioReportWithBLOBs.class);
|
return microService.getForDataArray(serviceName, BASE_URL + "/get/report/ext/" + planId, UiScenarioReportWithBLOBs.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, List<String>> getUiScenarioEnv(String planId) {
|
||||||
|
return microService.getForData(serviceName, BASE_URL + "/get/env/" + planId, Map.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import {get, post} from "metersphere-frontend/src/plugins/request"
|
||||||
|
|
||||||
|
const BASE_URL = "/ui/automation/";
|
||||||
|
|
||||||
|
export function getUiScenarioEnvByProjectId(id) {
|
||||||
|
return get(BASE_URL + `env-project-ids/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function uiAutomationReduction(param) {
|
||||||
|
return post(BASE_URL + 'reduction', param);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function uiScenarioEnvMap(params) {
|
||||||
|
return post(BASE_URL + 'env/map', params);
|
||||||
|
}
|
|
@ -201,7 +201,7 @@ export default {
|
||||||
// 选中环境是否存在
|
// 选中环境是否存在
|
||||||
temp.selectEnv = envs.filter(e => e.id === envId).length === 0 ? null : envId;
|
temp.selectEnv = envs.filter(e => e.id === envId).length === 0 ? null : envId;
|
||||||
}
|
}
|
||||||
if (this.projectEnvMap) {
|
if (this.projectEnvMap && Object.keys(this.projectEnvMap).length > 0) {
|
||||||
let projectEnvMapElement = this.projectEnvMap[d];
|
let projectEnvMapElement = this.projectEnvMap[d];
|
||||||
if (projectEnvMapElement.length>0) {
|
if (projectEnvMapElement.length>0) {
|
||||||
projectEnvMapElement.forEach(envId => {
|
projectEnvMapElement.forEach(envId => {
|
||||||
|
|
|
@ -1,5 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
|
<env-group-popover
|
||||||
|
:env-map="projectEnvMap"
|
||||||
|
:project-ids="projectIds"
|
||||||
|
:show-env-group="false"
|
||||||
|
@setProjectEnvMap="setProjectEnvMap"
|
||||||
|
:environment-type.sync="environmentType"
|
||||||
|
:group-id="envGroupId"
|
||||||
|
:is-scenario="false"
|
||||||
|
@setEnvGroup="setEnvGroup"
|
||||||
|
:show-config-button-with-out-permission="
|
||||||
|
showConfigButtonWithOutPermission
|
||||||
|
"
|
||||||
|
:project-list="projectList"
|
||||||
|
ref="envPopover"
|
||||||
|
class="env-popover"
|
||||||
|
/>
|
||||||
|
|
||||||
<ms-table-adv-search-bar :condition.sync="condition" class="adv-search-bar"
|
<ms-table-adv-search-bar :condition.sync="condition" class="adv-search-bar"
|
||||||
v-if="condition.components !== undefined && condition.components.length > 0"
|
v-if="condition.components !== undefined && condition.components.length > 0"
|
||||||
|
@ -99,6 +115,9 @@ import {
|
||||||
getCustomTableWidth
|
getCustomTableWidth
|
||||||
} from "metersphere-frontend/src/utils/tableUtils";
|
} from "metersphere-frontend/src/utils/tableUtils";
|
||||||
import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn";
|
import MsTableColumn from "metersphere-frontend/src/components/table/MsTableColumn";
|
||||||
|
import EnvGroupPopover from "@/business/plan/env/EnvGroupPopover";
|
||||||
|
import {getApiScenarioEnvByProjectId} from "@/api/remote/api/api-automation";
|
||||||
|
import {getUiScenarioEnvByProjectId} from "@/api/remote/ui/ui-automation";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "RelevanceUiScenarioList",
|
name: "RelevanceUiScenarioList",
|
||||||
|
@ -112,6 +131,7 @@ export default {
|
||||||
MsTag,
|
MsTag,
|
||||||
MsTableAdvSearchBar,
|
MsTableAdvSearchBar,
|
||||||
MsTableColumn,
|
MsTableColumn,
|
||||||
|
EnvGroupPopover,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
referenced: {
|
referenced: {
|
||||||
|
@ -147,6 +167,7 @@ export default {
|
||||||
envGroupId: "",
|
envGroupId: "",
|
||||||
versionFilters: [],
|
versionFilters: [],
|
||||||
fieldsWidth: getCustomTableWidth('TEST_PLAN_UI_SCENARIO_CASE'),
|
fieldsWidth: getCustomTableWidth('TEST_PLAN_UI_SCENARIO_CASE'),
|
||||||
|
projectIds: new Set()
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -244,10 +265,22 @@ export default {
|
||||||
selectCountChange(data) {
|
selectCountChange(data) {
|
||||||
this.selectRows = this.$refs.scenarioTable.selectRows;
|
this.selectRows = this.$refs.scenarioTable.selectRows;
|
||||||
this.$emit("selectCountChange", data);
|
this.$emit("selectCountChange", data);
|
||||||
|
this.initProjectIds();
|
||||||
},
|
},
|
||||||
showReport() {
|
showReport() {
|
||||||
|
|
||||||
}
|
},
|
||||||
|
initProjectIds() {
|
||||||
|
this.projectIds.clear();
|
||||||
|
// this.map.clear();
|
||||||
|
this.selectRows.forEach((row) => {
|
||||||
|
getUiScenarioEnvByProjectId(row.id).then((res) => {
|
||||||
|
let data = res.data;
|
||||||
|
data.projectIds.forEach((d) => this.projectIds.add(d));
|
||||||
|
// this.map.set(row.id, data.projectIds);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -148,6 +148,10 @@ export default {
|
||||||
let map = this.$refs.apiScenarioList.map;
|
let map = this.$refs.apiScenarioList.map;
|
||||||
let envGroupId = this.$refs.apiScenarioList.envGroupId;
|
let envGroupId = this.$refs.apiScenarioList.envGroupId;
|
||||||
|
|
||||||
|
if (!envMap || envMap.size == 0) {
|
||||||
|
this.$warning(this.$t('api_test.environment.select_environment'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
selectRows.forEach(row => {
|
selectRows.forEach(row => {
|
||||||
selectIds.push(row.id);
|
selectIds.push(row.id);
|
||||||
})
|
})
|
||||||
|
@ -179,8 +183,6 @@ export default {
|
||||||
this.autoCheckStatus();
|
this.autoCheckStatus();
|
||||||
this.$refs.baseRelevance.close();
|
this.$refs.baseRelevance.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
autoCheckStatus() { // 检查执行结果,自动更新计划状态
|
autoCheckStatus() { // 检查执行结果,自动更新计划状态
|
||||||
if (!this.planId) {
|
if (!this.planId) {
|
||||||
|
|
|
@ -147,7 +147,8 @@
|
||||||
:filters="apiscenariofilters.RESULT_FILTERS"
|
:filters="apiscenariofilters.RESULT_FILTERS"
|
||||||
:label="$t('api_test.automation.last_result')">
|
:label="$t('api_test.automation.last_result')">
|
||||||
<template v-slot:default="{row}">
|
<template v-slot:default="{row}">
|
||||||
<el-link @click="showReport(row)" :disabled="!row.lastResult || row.lastResult==='PENDING' || row.lastResult==='UnExecute'">
|
<el-link @click="showReport(row)"
|
||||||
|
:disabled="!row.lastResult || row.lastResult==='PENDING' || row.lastResult==='UnExecute'">
|
||||||
<ms-test-plan-api-status :status="row.lastResult==='UnExecute' ? 'PENDING' : row.lastResult"/>
|
<ms-test-plan-api-status :status="row.lastResult==='UnExecute' ? 'PENDING' : row.lastResult"/>
|
||||||
</el-link>
|
</el-link>
|
||||||
</template>
|
</template>
|
||||||
|
@ -177,7 +178,7 @@
|
||||||
@batchEdit="batchEdit"/>
|
@batchEdit="batchEdit"/>
|
||||||
|
|
||||||
<ui-run-mode @handleRunBatch="handleRunBatch" ref="runMode" :custom-run-mode="true"
|
<ui-run-mode @handleRunBatch="handleRunBatch" ref="runMode" :custom-run-mode="true"
|
||||||
:custom-serial-on-sample-error="true"/>
|
:custom-serial-on-sample-error="true" :request="conditionRequest"/>
|
||||||
|
|
||||||
<ms-task-center ref="taskCenter" :show-menu="false"/>
|
<ms-task-center ref="taskCenter" :show-menu="false"/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -327,6 +328,8 @@ export default {
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
versionFilters: [],
|
versionFilters: [],
|
||||||
|
//
|
||||||
|
conditionRequest: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -358,14 +361,14 @@ export default {
|
||||||
},
|
},
|
||||||
search() {
|
search() {
|
||||||
initCondition(this.condition, this.condition.selectAll);
|
initCondition(this.condition, this.condition.selectAll);
|
||||||
if(this.condition && this.condition.filters && this.condition.filters.last_result){
|
if (this.condition && this.condition.filters && this.condition.filters.last_result) {
|
||||||
if(this.condition.filters.last_result.length > 0){
|
if (this.condition.filters.last_result.length > 0) {
|
||||||
//校验是否含有PENDING
|
//校验是否含有PENDING
|
||||||
if(this.condition.filters.last_result.includes("PENDING")){
|
if (this.condition.filters.last_result.includes("PENDING")) {
|
||||||
this.condition.filters.last_result = [...this.condition.filters.last_result, "UnExecute"]
|
this.condition.filters.last_result = [...this.condition.filters.last_result, "UnExecute"]
|
||||||
}
|
}
|
||||||
//校验是否含有ERROR
|
//校验是否含有ERROR
|
||||||
if(this.condition.filters.last_result.includes("ERROR")){
|
if (this.condition.filters.last_result.includes("ERROR")) {
|
||||||
this.condition.filters.last_result = [...this.condition.filters.last_result, "FAIL"]
|
this.condition.filters.last_result = [...this.condition.filters.last_result, "FAIL"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,12 +440,19 @@ export default {
|
||||||
let rows = this.orderBySelectRows(this.$refs.table.selectRows);
|
let rows = this.orderBySelectRows(this.$refs.table.selectRows);
|
||||||
this.planCaseIds = [];
|
this.planCaseIds = [];
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
this.planCaseIds.push(row.id);
|
this.planCaseIds.push(row.caseId);
|
||||||
})
|
})
|
||||||
|
this.conditionRequest.id = getUUID();
|
||||||
|
this.conditionRequest.ids = this.planCaseIds;
|
||||||
|
this.conditionRequest.projectId = this.projectId;
|
||||||
|
this.conditionRequest.condition = this.condition;
|
||||||
this.$refs.runMode.open();
|
this.$refs.runMode.open();
|
||||||
},
|
},
|
||||||
orderBySelectRows(rows) {
|
orderBySelectRows(rows) {
|
||||||
let selectIds = Array.from(rows).map(row => row.id);
|
let selectIds = this.$refs.table.selectIds;
|
||||||
|
if (rows) {
|
||||||
|
selectIds = Array.from(rows).map(row => row.id);
|
||||||
|
}
|
||||||
let array = [];
|
let array = [];
|
||||||
for (let i in this.tableData) {
|
for (let i in this.tableData) {
|
||||||
if (selectIds.indexOf(this.tableData[i].id) !== -1) {
|
if (selectIds.indexOf(this.tableData[i].id) !== -1) {
|
||||||
|
|
|
@ -7,6 +7,21 @@
|
||||||
:visible.sync="runModeVisible"
|
:visible.sync="runModeVisible"
|
||||||
>
|
>
|
||||||
<div class="mode-container">
|
<div class="mode-container">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div>{{ $t("commons.environment") }}:</div>
|
||||||
|
<env-select-popover :project-ids="projectIds"
|
||||||
|
:project-list="projectList"
|
||||||
|
:project-env-map="projectEnvListMap"
|
||||||
|
:environment-type="'JSON'"
|
||||||
|
:has-option-group="false"
|
||||||
|
:group-id="runConfig.environmentGroupId"
|
||||||
|
@setProjectEnvMap="setProjectEnvMap"
|
||||||
|
ref="envSelectPopover"
|
||||||
|
class="mode-row"
|
||||||
|
></env-select-popover>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 浏览器 -->
|
<!-- 浏览器 -->
|
||||||
<div class="browser-row wrap">
|
<div class="browser-row wrap">
|
||||||
<div class="title">{{ $t("ui.browser") }}:</div>
|
<div class="title">{{ $t("ui.browser") }}:</div>
|
||||||
|
@ -175,11 +190,13 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter'
|
import MsDialogFooter from 'metersphere-frontend/src/components/MsDialogFooter'
|
||||||
import {getOwnerProjects} from "@/business/utils/sdk-utils";
|
import {getCurrentProjectID, getOwnerProjects, strMapToObj} from "@/business/utils/sdk-utils";
|
||||||
|
import {uiScenarioEnvMap} from "@/api/remote/ui/ui-automation";
|
||||||
|
import EnvSelectPopover from "@/business/plan/env/EnvSelectPopover";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "UiRunMode",
|
name: "UiRunMode",
|
||||||
components: {MsDialogFooter},
|
components: {MsDialogFooter, EnvSelectPopover},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
runModeVisible: false,
|
runModeVisible: false,
|
||||||
|
@ -207,6 +224,8 @@ export default {
|
||||||
},
|
},
|
||||||
projectList: [],
|
projectList: [],
|
||||||
projectIds: new Set(),
|
projectIds: new Set(),
|
||||||
|
projectEnvListMap: {},
|
||||||
|
caseIdEnvNameMap: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
@ -262,6 +281,7 @@ export default {
|
||||||
};
|
};
|
||||||
this.runModeVisible = true;
|
this.runModeVisible = true;
|
||||||
this.getWsProjects();
|
this.getWsProjects();
|
||||||
|
this.showPopover();
|
||||||
},
|
},
|
||||||
changeMode() {
|
changeMode() {
|
||||||
this.runConfig.runWithinResourcePool = false;
|
this.runConfig.runWithinResourcePool = false;
|
||||||
|
@ -296,6 +316,29 @@ export default {
|
||||||
this.$emit("handleRunBatch", this.runConfig);
|
this.$emit("handleRunBatch", this.runConfig);
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
|
setProjectEnvMap(projectEnvMap) {
|
||||||
|
this.runConfig.envMap = strMapToObj(projectEnvMap);
|
||||||
|
},
|
||||||
|
showPopover() {
|
||||||
|
this.showScenarioPopover();
|
||||||
|
},
|
||||||
|
showScenarioPopover() {
|
||||||
|
let currentProjectID = getCurrentProjectID();
|
||||||
|
this.projectIds.clear();
|
||||||
|
uiScenarioEnvMap(this.request).then((res) => {
|
||||||
|
let data = res.data;
|
||||||
|
this.projectEnvListMap = data;
|
||||||
|
if (data) {
|
||||||
|
for (let d in data) {
|
||||||
|
this.projectIds.add(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.projectIds.size === 0) {
|
||||||
|
this.projectIds.add(currentProjectID);
|
||||||
|
}
|
||||||
|
this.$refs.envSelectPopover.open();
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -88,6 +88,7 @@ const TRACK_HEADER = {
|
||||||
{id: 'name', key: '2', label: 'api_test.automation.scenario_name'},
|
{id: 'name', key: '2', label: 'api_test.automation.scenario_name'},
|
||||||
{id: 'versionId', key: 'd', label: 'commons.version'},
|
{id: 'versionId', key: 'd', label: 'commons.version'},
|
||||||
{id: 'level', key: '3', label: 'api_test.automation.case_level'},
|
{id: 'level', key: '3', label: 'api_test.automation.case_level'},
|
||||||
|
{id: 'envs', key: '8', label: 'commons.environment'},
|
||||||
{id: 'tagNames', key: '4', label: 'api_test.automation.tag'},
|
{id: 'tagNames', key: '4', label: 'api_test.automation.tag'},
|
||||||
{id: 'stepTotal', key: '7', label: 'api_test.automation.step'},
|
{id: 'stepTotal', key: '7', label: 'api_test.automation.step'},
|
||||||
{id: 'passRate', key: '9', label: 'api_test.automation.passing_rate'},
|
{id: 'passRate', key: '9', label: 'api_test.automation.passing_rate'},
|
||||||
|
|
Loading…
Reference in New Issue