feat(接口自动化) 场景增加执行功能,增加启用场景环境功能

This commit is contained in:
fit2-zhao 2021-09-27 11:57:27 +08:00 committed by fit2-zhao
parent 5a28e6d6d3
commit dd10ae60a6
9 changed files with 189 additions and 24 deletions

View File

@ -353,5 +353,11 @@ public class ApiAutomationController {
return apiAutomationService.exportJmx(request); return apiAutomationService.exportJmx(request);
} }
@PostMapping(value = "/checkScenarioEnv")
public boolean checkScenarioEnv(@RequestBody ApiScenarioWithBLOBs request) {
return apiAutomationService.checkScenarioEnv(request);
}
} }

View File

@ -304,7 +304,28 @@ public class ElementUtil {
try { try {
for (int i = 0; i < hashTree.size(); i++) { for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i); JSONObject element = hashTree.getJSONObject(i);
if (element != null && element.get("type").toString().equals("HTTPSamplerProxy")) { boolean isScenarioEnv = false;
ParameterConfig config = new ParameterConfig();
if (element != null && element.get("type").toString().equals("scenario")) {
MsScenario scenario = JSONObject.toJavaObject(element, MsScenario.class);
if (scenario.isEnvironmentEnable()) {
isScenarioEnv = true;
Map<String, EnvironmentConfig> envConfig = new HashMap<>(16);
Map<String, String> environmentMap = (Map<String, String>) element.get("environmentMap");
if (environmentMap != null && !environmentMap.isEmpty()) {
environmentMap.keySet().forEach(projectId -> {
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
ApiTestEnvironmentWithBLOBs environment = environmentService.get(environmentMap.get(projectId));
if (environment != null && environment.getConfig() != null) {
EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
env.setApiEnvironmentid(environment.getId());
envConfig.put(projectId, env);
}
});
config.setConfig(envConfig);
}
}
} else if (element != null && element.get("type").toString().equals("HTTPSamplerProxy")) {
MsHTTPSamplerProxy httpSamplerProxy = JSON.toJavaObject(element, MsHTTPSamplerProxy.class); MsHTTPSamplerProxy httpSamplerProxy = JSON.toJavaObject(element, MsHTTPSamplerProxy.class);
if (httpSamplerProxy != null if (httpSamplerProxy != null
&& (!httpSamplerProxy.isCustomizeReq() || (httpSamplerProxy.isCustomizeReq() && httpSamplerProxy.getIsRefEnvironment()))) { && (!httpSamplerProxy.isCustomizeReq() || (httpSamplerProxy.isCustomizeReq() && httpSamplerProxy.getIsRefEnvironment()))) {
@ -320,7 +341,11 @@ public class ElementUtil {
} }
if (element.containsKey("hashTree")) { if (element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree"); JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataSetDomain(elementJSONArray, msParameter); if (isScenarioEnv) {
dataSetDomain(elementJSONArray, config);
} else {
dataSetDomain(elementJSONArray, msParameter);
}
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -64,9 +64,12 @@ public class MsScenario extends MsTestElement {
@JSONField(ordinal = 27) @JSONField(ordinal = 27)
private Map<String, String> environmentMap; private Map<String, String> environmentMap;
@JSONField(ordinal = 24) @JSONField(ordinal = 28)
private Boolean onSampleError; private Boolean onSampleError;
@JSONField(ordinal = 29)
private boolean environmentEnable;
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR; private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
public MsScenario() { public MsScenario() {
@ -152,8 +155,7 @@ public class MsScenario extends MsTestElement {
} }
} else { } else {
Map<String, EnvironmentConfig> map = config.getConfig(); Map<String, EnvironmentConfig> map = config.getConfig();
for (EnvironmentConfig evnConfig : for (EnvironmentConfig evnConfig : map.values()) {
map.values()) {
if (evnConfig.getHttpConfig() != null) { if (evnConfig.getHttpConfig() != null) {
this.setMockEnvironment(evnConfig.getHttpConfig().isMock()); this.setMockEnvironment(evnConfig.getHttpConfig().isMock());
} }
@ -174,12 +176,32 @@ public class MsScenario extends MsTestElement {
//setHeader(tree, this.headers); //setHeader(tree, this.headers);
config.setHeaders(this.headers); config.setHeaders(this.headers);
} }
ParameterConfig newConfig = new ParameterConfig();
if (this.isEnvironmentEnable() && this.environmentMap != null && !this.environmentMap.isEmpty()) {
environmentMap.keySet().forEach(projectId -> {
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
ApiTestEnvironmentWithBLOBs environment = environmentService.get(this.environmentMap.get(projectId));
if (environment != null && environment.getConfig() != null) {
EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
env.setApiEnvironmentid(environment.getId());
envConfig.put(projectId, env);
if (StringUtils.equals(environment.getName(), MockConfigStaticData.MOCK_EVN_NAME)) {
this.setMockEnvironment(true);
}
}
});
newConfig.setConfig(envConfig);
}
if (CollectionUtils.isNotEmpty(hashTree)) { if (CollectionUtils.isNotEmpty(hashTree)) {
for (MsTestElement el : hashTree) { for (MsTestElement el : hashTree) {
// 给所有孩子加一个父亲标志 // 给所有孩子加一个父亲标志
el.setParent(this); el.setParent(this);
el.setMockEnvironment(this.isMockEnvironment()); el.setMockEnvironment(this.isMockEnvironment());
el.toHashTree(tree, el.getHashTree(), config); if (this.isEnvironmentEnable()) {
el.toHashTree(tree, el.getHashTree(), newConfig);
} else {
el.toHashTree(tree, el.getHashTree(), config);
}
} }
} }
} }

View File

@ -714,6 +714,10 @@ public class ApiAutomationService {
} }
if (StringUtils.equals(tr.getType(), "scenario")) { if (StringUtils.equals(tr.getType(), "scenario")) {
MsScenario scenario = (MsScenario) tr;
if (scenario.isEnvironmentEnable()) {
continue;
}
env.getProjectIds().add(tr.getProjectId()); env.getProjectIds().add(tr.getProjectId());
} }
if (CollectionUtils.isNotEmpty(tr.getHashTree())) { if (CollectionUtils.isNotEmpty(tr.getHashTree())) {
@ -786,6 +790,10 @@ public class ApiAutomationService {
} }
} }
if (StringUtils.equals(tr.getType(), "scenario")) { if (StringUtils.equals(tr.getType(), "scenario")) {
MsScenario scenario = (MsScenario) tr;
if (scenario.isEnvironmentEnable()) {
continue;
}
env.getProjectIds().add(tr.getProjectId()); env.getProjectIds().add(tr.getProjectId());
} }
if (CollectionUtils.isNotEmpty(tr.getHashTree())) { if (CollectionUtils.isNotEmpty(tr.getHashTree())) {
@ -1952,14 +1960,14 @@ public class ApiAutomationService {
hashTree.set(i, object); hashTree.set(i, object);
} }
} else { } else {
ApiScenarioWithBLOBs bloBs = this.getDto(object.getString("id")); ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString("id"));
if (bloBs != null) { if (bloBs != null) {
object = JSON.parseObject(bloBs.getScenarioDefinition()); object = JSON.parseObject(bloBs.getScenarioDefinition());
hashTree.set(i, object); hashTree.set(i, object);
} }
} }
} else if ("scenario".equals(object.getString("type"))) { } else if ("scenario".equals(object.getString("type"))) {
ApiScenarioWithBLOBs bloBs = this.getDto(object.getString("id")); ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString("id"));
if (bloBs != null) { if (bloBs != null) {
object = JSON.parseObject(bloBs.getScenarioDefinition()); object = JSON.parseObject(bloBs.getScenarioDefinition());
hashTree.set(i, object); hashTree.set(i, object);
@ -2610,4 +2618,9 @@ public class ApiAutomationService {
extApiScenarioMapper::getLastOrder, extApiScenarioMapper::getLastOrder,
apiScenarioMapper::updateByPrimaryKeySelective); apiScenarioMapper::updateByPrimaryKeySelective);
} }
public boolean checkScenarioEnv(ApiScenarioWithBLOBs request) {
return this.checkScenarioEnv(request, null);
}
} }

View File

@ -214,6 +214,8 @@
@copyRow="copyRow" @copyRow="copyRow"
@suggestClick="suggestClick" @suggestClick="suggestClick"
@refReload="refReload" @refReload="refReload"
@runScenario="runDebug"
@stopScenario="stop"
@openScenario="openScenario"/> @openScenario="openScenario"/>
</span> </span>
</el-tree> </el-tree>
@ -454,6 +456,7 @@ export default {
stepFilter: new STEP, stepFilter: new STEP,
plugins: [], plugins: [],
clearMessage: "", clearMessage: "",
runScenario: undefined,
} }
}, },
created() { created() {
@ -571,6 +574,7 @@ export default {
this.debugLoading = false; this.debugLoading = false;
} }
}); });
this.runScenario = undefined;
}, },
clearDebug() { clearDebug() {
this.reqError = 0; this.reqError = 0;
@ -655,7 +659,9 @@ export default {
this.message = getUUID(); this.message = getUUID();
if (data.end) { if (data.end) {
this.removeReport(); this.removeReport();
this.runScenario = undefined;
this.debugLoading = false; this.debugLoading = false;
this.message = "stop";
this.stopDebug = "stop"; this.stopDebug = "stop";
} }
} }
@ -775,7 +781,11 @@ export default {
this.reqTotalTime = endTime - startTime + 100; this.reqTotalTime = endTime - startTime + 100;
} }
this.debugResult = resMap; this.debugResult = resMap;
this.sort(); if (this.runScenario && this.runScenario.hashTree) {
this.sort(this.runScenario.hashTree);
} else {
this.sort();
}
this.reloadDebug = getUUID(); this.reloadDebug = getUUID();
}, },
removeReport() { removeReport() {
@ -1127,7 +1137,7 @@ export default {
this.showHideTree = true this.showHideTree = true
}); });
}, },
runDebug() { runDebug(runScenario) {
if (this.scenarioDefinition.length < 1) { if (this.scenarioDefinition.length < 1) {
return; return;
} }
@ -1149,22 +1159,32 @@ export default {
this.clearMessage = getUUID().substring(0, 8); this.clearMessage = getUUID().substring(0, 8);
return; return;
} }
let scenario = undefined;
if (runScenario && runScenario.type === 'scenario') {
scenario = runScenario;
this.runScenario = runScenario;
}
// //
this.debugData = { this.debugData = {
id: this.currentScenario.id, id: scenario ? scenario.id : this.currentScenario.id,
name: this.currentScenario.name, name: scenario ? scenario.name : this.currentScenario.name,
type: "scenario", type: "scenario",
variables: this.currentScenario.variables, variables: scenario ? scenario.variables : this.currentScenario.variables,
referenced: 'Created', referenced: 'Created',
enableCookieShare: this.enableCookieShare, enableCookieShare: scenario ? scenario.enableCookieShare : this.enableCookieShare,
headers: this.currentScenario.headers, headers: scenario ? scenario.headers : this.currentScenario.headers,
environmentMap: this.projectEnvMap, environmentMap: scenario && scenario.environmentEnable ? scenario.environmentMap : this.projectEnvMap,
hashTree: this.scenarioDefinition, hashTree: scenario ? scenario.hashTree : this.scenarioDefinition,
onSampleError: this.onSampleError, onSampleError: scenario ? scenario.onSampleError : this.onSampleError,
}; };
if (scenario && scenario.environmentEnable) {
this.debugData.environmentEnable = scenario.environmentEnable;
this.debugLoading = false;
}else{
this.debugLoading = true;
}
this.reportId = getUUID().substring(0, 8); this.reportId = getUUID().substring(0, 8);
this.debug = true; this.debug = true;
this.debugLoading = true;
}) })
}) })
} else { } else {
@ -1219,8 +1239,7 @@ export default {
} }
return true; return true;
} else if (dropType === "inner" && dropNode.data.referenced !== 'REF' && dropNode.data.referenced !== 'Deleted' } else if (dropType === "inner" && dropNode.data.referenced !== 'REF' && dropNode.data.referenced !== 'Deleted'
&& (this.stepFilter.get(dropNode.data.type) && this.stepFilter.get(dropNode.data.type).indexOf(draggingNode.data.type) != -1) && (this.stepFilter.get(dropNode.data.type) && this.stepFilter.get(dropNode.data.type).indexOf(draggingNode.data.type) != -1)) {
&& !draggingNode.data.disabled) {
return true; return true;
} }
return false; return false;
@ -1412,6 +1431,8 @@ export default {
this.debugLoading = false; this.debugLoading = false;
this.debugVisible = false; this.debugVisible = false;
this.loading = false; this.loading = false;
this.runScenario = undefined;
this.message = "stop";
this.clearMessage = getUUID().substring(0, 8); this.clearMessage = getUUID().substring(0, 8);
}, },
showScenarioParameters() { showScenarioParameters() {

View File

@ -26,6 +26,9 @@
</el-tooltip> </el-tooltip>
</span> </span>
</slot> </slot>
<slot name="scenarioEnable"/>
</span> </span>
<div class="header-right" @click.stop> <div class="header-right" @click.stop>

View File

@ -19,7 +19,6 @@
<el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='Deleted'" type="danger">{{ $t('api_test.automation.reference_deleted') }}</el-tag> <el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='Deleted'" type="danger">{{ $t('api_test.automation.reference_deleted') }}</el-tag>
<el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag> <el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='Copy'">{{ $t('commons.copy') }}</el-tag>
<el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='REF'">{{ $t('api_test.scenario.reference') }}</el-tag> <el-tag size="mini" class="ms-tag" v-if="scenario.referenced==='REF'">{{ $t('api_test.scenario.reference') }}</el-tag>
<span class="ms-tag">{{ getProjectName(scenario.projectId) }}</span> <span class="ms-tag">{{ getProjectName(scenario.projectId) }}</span>
</template> </template>
<template v-slot:debugStepCode> <template v-slot:debugStepCode>
@ -31,6 +30,23 @@
{{ getCode() }} {{ getCode() }}
</span> </span>
</template> </template>
<template v-slot:scenarioEnable>
<el-tooltip content="启用场景环境:当前步骤使用场景原始环境配置运行" placement="top">
<el-checkbox v-model="scenario.environmentEnable" @change="checkEnv">启用场景环境</el-checkbox>
</el-tooltip>
</template>
<template v-slot:button>
<el-tooltip :content="$t('api_test.run')" placement="top" v-if="!scenario.run">
<el-button :disabled="!scenario.enable" @click="run" icon="el-icon-video-play" style="padding: 5px" class="ms-btn" size="mini" circle/>
</el-tooltip>
<el-tooltip :content="$t('report.stop_btn')" placement="top" :enterable="false" v-else>
<el-button :disabled="!scenario.enable" @click.once="stop" size="mini" style="color:white;padding: 0 0.1px;width: 24px;height: 24px;" class="stop-btn" circle>
<div style="transform: scale(0.66)">
<span style="margin-left: -4.5px;font-weight: bold;">STOP</span>
</div>
</el-button>
</el-tooltip>
</template>
</api-base-component> </api-base-component>
</template> </template>
@ -66,6 +82,9 @@ export default {
}, },
watch: { watch: {
message() { message() {
if (this.message === "stop") {
this.scenario.run = false;
}
this.reload(); this.reload();
}, },
}, },
@ -121,6 +140,35 @@ export default {
}, },
}, },
methods: { methods: {
run() {
this.scenario.run = true;
this.$emit('runScenario', this.scenario);
},
stop() {
this.scenario.run = false;
this.$emit('stopScenario');
this.reload();
},
checkEnv() {
this.$post("/api/automation/checkScenarioEnv", {scenarioDefinition: JSON.stringify(this.scenario), projectId: this.projectId}, res => {
if (this.scenario.environmentEnable && !res.data) {
this.scenario.environmentEnable = false;
this.$warning("当前场景没有环境,需要先设置自身环境");
return;
}
this.setDomain();
});
},
setDomain() {
if (this.scenario.environmentEnable) {
this.$post("/api/automation/setDomain", {definition: JSON.stringify(this.scenario)}, res => {
if (res.data) {
let data = JSON.parse(res.data);
this.scenario.hashTree = data.hashTree;
}
})
}
},
getCode() { getCode() {
if (this.node && this.node.data.code && this.node.data.debug) { if (this.node && this.node.data.code && this.node.data.debug) {
if (this.node.data.code && this.node.data.code === 'error') { if (this.node.data.code && this.node.data.code === 'error') {
@ -210,10 +258,30 @@ export default {
color: #F56C6C; color: #F56C6C;
} }
.ms-test-running {
color: #6D317C;
}
.ms-req-success { .ms-req-success {
color: #67C23A; color: #67C23A;
} }
.ms-btn {
background-color: #409EFF;
color: white;
}
.ms-btn-flot {
margin: 20px;
float: right;
}
.stop-btn {
background-color: #E62424;
border-color: #EE6161;
color: white;
}
.ms-step-debug-code { .ms-step-debug-code {
display: inline-block; display: inline-block;
margin: 0 5px; margin: 0 5px;
@ -224,6 +292,7 @@ export default {
white-space: nowrap; white-space: nowrap;
width: 60px; width: 60px;
} }
.ms-test-running { .ms-test-running {
color: #6D317C; color: #6D317C;
} }

View File

@ -4,7 +4,7 @@
<component v-bind:is="component" :isMax="isMax" :show-btn="showBtn" :expandedNode="expandedNode" <component v-bind:is="component" :isMax="isMax" :show-btn="showBtn" :expandedNode="expandedNode"
:scenario="scenario" :controller="scenario" :timer="scenario" :assertions="scenario" :extract="scenario" :jsr223-processor="scenario" :request="scenario" :currentScenario="currentScenario" :currentEnvironmentId="currentEnvironmentId" :node="node" :scenario="scenario" :controller="scenario" :timer="scenario" :assertions="scenario" :extract="scenario" :jsr223-processor="scenario" :request="scenario" :currentScenario="currentScenario" :currentEnvironmentId="currentEnvironmentId" :node="node"
:draggable="draggable" :title="title" :color="titleColor" :background-color="backgroundColor" @suggestClick="suggestClick(node)" :response="response" :draggable="draggable" :title="title" :color="titleColor" :background-color="backgroundColor" @suggestClick="suggestClick(node)" :response="response"
@remove="remove" @copyRow="copyRow" @refReload="refReload" @openScenario="openScenario" :project-list="projectList" :env-map="envMap" :message="message"/> @remove="remove" @runScenario="runScenario" @stopScenario="stopScenario" @copyRow="copyRow" @refReload="refReload" @openScenario="openScenario" :project-list="projectList" :env-map="envMap" :message="message"/>
</keep-alive> </keep-alive>
</div> </div>
</template> </template>
@ -184,6 +184,12 @@ export default {
}, },
refReload(data, node) { refReload(data, node) {
this.$emit('refReload', data, node); this.$emit('refReload', data, node);
},
runScenario(scenario) {
this.$emit('runScenario', scenario);
},
stopScenario(){
this.$emit('stopScenario');
} }
} }
} }

View File

@ -412,7 +412,7 @@ export default {
}, },
data:{ data:{
handler:function(){ handler:function(){
if(this.defaultKey && this.defaultKey.length > 0){ if(this.defaultKey && this.defaultKey.length > 0 && this.defaultKey instanceof Array){
this.$refs.tree.setCheckedKeys(this.defaultKey); this.$refs.tree.setCheckedKeys(this.defaultKey);
} }
}, },