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);
}
@PostMapping(value = "/checkScenarioEnv")
public boolean checkScenarioEnv(@RequestBody ApiScenarioWithBLOBs request) {
return apiAutomationService.checkScenarioEnv(request);
}
}

View File

@ -304,7 +304,28 @@ public class ElementUtil {
try {
for (int i = 0; i < hashTree.size(); 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);
if (httpSamplerProxy != null
&& (!httpSamplerProxy.isCustomizeReq() || (httpSamplerProxy.isCustomizeReq() && httpSamplerProxy.getIsRefEnvironment()))) {
@ -320,7 +341,11 @@ public class ElementUtil {
}
if (element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataSetDomain(elementJSONArray, msParameter);
if (isScenarioEnv) {
dataSetDomain(elementJSONArray, config);
} else {
dataSetDomain(elementJSONArray, msParameter);
}
}
}
} catch (Exception e) {

View File

@ -64,9 +64,12 @@ public class MsScenario extends MsTestElement {
@JSONField(ordinal = 27)
private Map<String, String> environmentMap;
@JSONField(ordinal = 24)
@JSONField(ordinal = 28)
private Boolean onSampleError;
@JSONField(ordinal = 29)
private boolean environmentEnable;
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
public MsScenario() {
@ -152,8 +155,7 @@ public class MsScenario extends MsTestElement {
}
} else {
Map<String, EnvironmentConfig> map = config.getConfig();
for (EnvironmentConfig evnConfig :
map.values()) {
for (EnvironmentConfig evnConfig : map.values()) {
if (evnConfig.getHttpConfig() != null) {
this.setMockEnvironment(evnConfig.getHttpConfig().isMock());
}
@ -174,12 +176,32 @@ public class MsScenario extends MsTestElement {
//setHeader(tree, 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)) {
for (MsTestElement el : hashTree) {
// 给所有孩子加一个父亲标志
el.setParent(this);
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")) {
MsScenario scenario = (MsScenario) tr;
if (scenario.isEnvironmentEnable()) {
continue;
}
env.getProjectIds().add(tr.getProjectId());
}
if (CollectionUtils.isNotEmpty(tr.getHashTree())) {
@ -786,6 +790,10 @@ public class ApiAutomationService {
}
}
if (StringUtils.equals(tr.getType(), "scenario")) {
MsScenario scenario = (MsScenario) tr;
if (scenario.isEnvironmentEnable()) {
continue;
}
env.getProjectIds().add(tr.getProjectId());
}
if (CollectionUtils.isNotEmpty(tr.getHashTree())) {
@ -1952,14 +1960,14 @@ public class ApiAutomationService {
hashTree.set(i, object);
}
} else {
ApiScenarioWithBLOBs bloBs = this.getDto(object.getString("id"));
ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString("id"));
if (bloBs != null) {
object = JSON.parseObject(bloBs.getScenarioDefinition());
hashTree.set(i, object);
}
}
} else if ("scenario".equals(object.getString("type"))) {
ApiScenarioWithBLOBs bloBs = this.getDto(object.getString("id"));
ApiScenarioWithBLOBs bloBs = apiScenarioMapper.selectByPrimaryKey(object.getString("id"));
if (bloBs != null) {
object = JSON.parseObject(bloBs.getScenarioDefinition());
hashTree.set(i, object);
@ -2610,4 +2618,9 @@ public class ApiAutomationService {
extApiScenarioMapper::getLastOrder,
apiScenarioMapper::updateByPrimaryKeySelective);
}
public boolean checkScenarioEnv(ApiScenarioWithBLOBs request) {
return this.checkScenarioEnv(request, null);
}
}

View File

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

View File

@ -26,6 +26,9 @@
</el-tooltip>
</span>
</slot>
<slot name="scenarioEnable"/>
</span>
<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==='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>
<span class="ms-tag">{{ getProjectName(scenario.projectId) }}</span>
</template>
<template v-slot:debugStepCode>
@ -31,6 +30,23 @@
{{ getCode() }}
</span>
</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>
</template>
@ -66,6 +82,9 @@ export default {
},
watch: {
message() {
if (this.message === "stop") {
this.scenario.run = false;
}
this.reload();
},
},
@ -121,6 +140,35 @@ export default {
},
},
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() {
if (this.node && this.node.data.code && this.node.data.debug) {
if (this.node.data.code && this.node.data.code === 'error') {
@ -210,10 +258,30 @@ export default {
color: #F56C6C;
}
.ms-test-running {
color: #6D317C;
}
.ms-req-success {
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 {
display: inline-block;
margin: 0 5px;
@ -224,6 +292,7 @@ export default {
white-space: nowrap;
width: 60px;
}
.ms-test-running {
color: #6D317C;
}

View File

@ -4,7 +4,7 @@
<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"
: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>
</div>
</template>
@ -184,6 +184,12 @@ export default {
},
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:{
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);
}
},