fix(接口自动化): 部分缺陷修复

This commit is contained in:
fit2-zhao 2021-04-15 20:42:51 +08:00 committed by fit2-zhao
parent c8143a0f1f
commit f9aece0463
13 changed files with 96 additions and 37 deletions

View File

@ -27,8 +27,10 @@ import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.service.ApiDefinitionService; import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.api.service.ApiTestCaseService;
import io.metersphere.api.service.ApiTestEnvironmentService; import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs; import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.commons.constants.LoopConstants; import io.metersphere.commons.constants.LoopConstants;
import io.metersphere.commons.constants.MsTestElementConstants; import io.metersphere.commons.constants.MsTestElementConstants;
@ -158,12 +160,23 @@ public abstract class MsTestElement {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class); ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(element.getId()); if (StringUtils.equals(element.getRefType(), "CASE")) {
if (apiDefinition != null) { ApiTestCaseService apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
element.setProjectId(apiDefinition.getProjectId()); ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(element.getId());
element = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsTestElement>() { if (bloBs != null) {
}); element.setProjectId(bloBs.getProjectId());
hashTree.add(element); element = mapper.readValue(bloBs.getRequest(), new TypeReference<MsTestElement>() {
});
hashTree.add(element);
}
} else {
ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(element.getId());
if (apiDefinition != null) {
element.setProjectId(apiDefinition.getProjectId());
element = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsTestElement>() {
});
hashTree.add(element);
}
} }
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();

View File

@ -2,6 +2,9 @@ package io.metersphere.api.dto.definition.request.sampler;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.annotation.JSONType;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.metersphere.api.dto.definition.request.MsTestElement; import io.metersphere.api.dto.definition.request.MsTestElement;
import io.metersphere.api.dto.definition.request.ParameterConfig; import io.metersphere.api.dto.definition.request.ParameterConfig;
import io.metersphere.api.dto.definition.request.auth.MsAuthManager; import io.metersphere.api.dto.definition.request.auth.MsAuthManager;
@ -11,10 +14,10 @@ import io.metersphere.api.dto.scenario.HttpConfig;
import io.metersphere.api.dto.scenario.HttpConfigCondition; import io.metersphere.api.dto.scenario.HttpConfigCondition;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.service.ApiDefinitionService; import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.api.service.ApiModuleService; import io.metersphere.api.service.ApiTestCaseService;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.ApiDefinition; import io.metersphere.base.domain.ApiDefinition;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs; import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.commons.constants.ConditionType; import io.metersphere.commons.constants.ConditionType;
import io.metersphere.commons.constants.MsTestElementConstants; import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
@ -102,6 +105,35 @@ public class MsHTTPSamplerProxy extends MsTestElement {
@JSONField(ordinal = 36) @JSONField(ordinal = 36)
private MsAuthManager authManager; private MsAuthManager authManager;
public void setRefElement() {
try {
ApiDefinitionService apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
if (StringUtils.equals(this.getRefType(), "CASE")) {
ApiTestCaseService apiTestCaseService = CommonBeanFactory.getBean(ApiTestCaseService.class);
ApiTestCaseWithBLOBs bloBs = apiTestCaseService.get(this.getId());
if (bloBs != null) {
this.setProjectId(bloBs.getProjectId());
MsHTTPSamplerProxy proxy = mapper.readValue(bloBs.getRequest(), new TypeReference<MsHTTPSamplerProxy>() {
});
this.setHashTree(proxy.getHashTree());
}
} else {
ApiDefinitionWithBLOBs apiDefinition = apiDefinitionService.getBLOBs(this.getId());
if (apiDefinition != null) {
this.setProjectId(apiDefinition.getProjectId());
MsHTTPSamplerProxy proxy = mapper.readValue(apiDefinition.getRequest(), new TypeReference<MsHTTPSamplerProxy>() {
});
this.setHashTree(proxy.getHashTree());
}
}
} catch (Exception ex) {
ex.printStackTrace();
LogUtil.error(ex.getMessage());
}
}
@Override @Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) { public void toHashTree(HashTree tree, List<MsTestElement> hashTree, ParameterConfig config) {
// 非导出操作且不是启用状态则跳过执行 // 非导出操作且不是启用状态则跳过执行
@ -109,7 +141,8 @@ public class MsHTTPSamplerProxy extends MsTestElement {
return; return;
} }
if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) { if (this.getReferenced() != null && MsTestElementConstants.REF.name().equals(this.getReferenced())) {
this.getRefElement(this); this.setRefElement();
hashTree = this.getHashTree();
} }
HTTPSamplerProxy sampler = new HTTPSamplerProxy(); HTTPSamplerProxy sampler = new HTTPSamplerProxy();
sampler.setEnabled(this.isEnable()); sampler.setEnabled(this.isEnable());

View File

@ -180,6 +180,9 @@
} }
}, },
addTab(tab) { addTab(tab) {
if(tab.name==='default'){
this.$refs.apiScenarioList.search();
}
if (!this.projectId) { if (!this.projectId) {
this.$warning(this.$t('commons.check_project_tip')); this.$warning(this.$t('commons.check_project_tip'));
return; return;

View File

@ -12,7 +12,7 @@
<el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-left:10px; margin-top: 10px;" <el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-left:10px; margin-top: 10px;"
size="small"> size="small">
<el-option v-for="(environment, index) in pe.envs" :key="index" <el-option v-for="(environment, index) in pe.envs" :key="index"
:label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')" :label="environment.name"
:value="environment.id"/> :value="environment.id"/>
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)"> <el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
{{ $t('api_test.environment.environment_config') }} {{ $t('api_test.environment.environment_config') }}

View File

@ -553,8 +553,6 @@ export default {
if (!(environment.config instanceof Object)) { if (!(environment.config instanceof Object)) {
environment.config = JSON.parse(environment.config); environment.config = JSON.parse(environment.config);
} }
environment.name = environment.name + (environment.config.httpConfig.socket ?
(': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '');
}); });
}); });
}, },

View File

@ -3,7 +3,7 @@
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px;"> <div v-for="pe in data" :key="pe.id" style="margin-left: 20px;">
<el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-top: 8px;width: 200px;" size="small"> <el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-top: 8px;width: 200px;" size="small">
<el-option v-for="(environment, index) in pe.envs" :key="index" <el-option v-for="(environment, index) in pe.envs" :key="index"
:label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')" :label="environment.name"
:value="environment.id"/> :value="environment.id"/>
<el-button class="ms-scenario-button" size="mini" type="primary" <el-button class="ms-scenario-button" size="mini" type="primary"
@click="openEnvironmentConfig(pe.id, pe['selectEnv'])"> @click="openEnvironmentConfig(pe.id, pe['selectEnv'])">

View File

@ -19,7 +19,7 @@
<el-radio label="setReport">{{ $t("run_mode.set_report") }}</el-radio> <el-radio label="setReport">{{ $t("run_mode.set_report") }}</el-radio>
</el-radio-group> </el-radio-group>
</div> </div>
<div class="ms-mode-div" v-if="runConfig.reportType === 'setReport'"> <div class="ms-mode-div" v-if="runConfig.reportType === 'setReport' && runConfig.mode==='serial'">
<span class="ms-mode-span">{{ $t("run_mode.report_name") }}</span> <span class="ms-mode-span">{{ $t("run_mode.report_name") }}</span>
<el-input <el-input
v-model="runConfig.reportName" v-model="runConfig.reportName"

View File

@ -3,7 +3,7 @@
<el-select :disabled="isReadOnly" v-model="environmentId" size="small" class="environment-select" <el-select :disabled="isReadOnly" v-model="environmentId" size="small" class="environment-select"
:placeholder="$t('api_test.definition.request.run_env')" clearable> :placeholder="$t('api_test.definition.request.run_env')" clearable>
<el-option v-for="(environment, key) in environments" :key="key" <el-option v-for="(environment, key) in environments" :key="key"
:label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')" :label="environment.name"
:value="environment.id"/> :value="environment.id"/>
<el-button class="environment-button" size="mini" type="primary" @click="openEnvironmentConfig"> <el-button class="environment-button" size="mini" type="primary" @click="openEnvironmentConfig">
{{ $t('api_test.environment.environment_config') }} {{ $t('api_test.environment.environment_config') }}

View File

@ -79,8 +79,7 @@
return environment.name; return environment.name;
} }
} }
return environment.name + (environment.config.httpConfig.socket ? return environment.name;
(': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '');
} }
return ""; return "";
}, },

View File

@ -632,6 +632,9 @@ export default {
row.request = JSON.parse(row.request); row.request = JSON.parse(row.request);
row.request.name = row.id; row.request.name = row.id;
row.request.useEnvironment = environment.id; row.request.useEnvironment = environment.id;
let map = new Map;
map.set(row.projectId,environment.id);
row.environmentMap = map;
runData.push(row.request); runData.push(row.request);
/*触发执行操作*/ /*触发执行操作*/
let testPlan = new TestPlan(); let testPlan = new TestPlan();

View File

@ -46,7 +46,7 @@
this.$warning(this.$t('api_test.automation.save_case_info')) this.$warning(this.$t('api_test.automation.save_case_info'))
} }
}, },
createPerformance(row){ createPerformance(row) {
/** /**
* 思路调用后台创建性能测试的方法把当前案例的hashTree在后台转化为jmx并文件创建性能测试 * 思路调用后台创建性能测试的方法把当前案例的hashTree在后台转化为jmx并文件创建性能测试
* 然后跳转到修改性能测试的页面 * 然后跳转到修改性能测试的页面
@ -61,7 +61,7 @@
this.runData = []; this.runData = [];
this.singleLoading = true; this.singleLoading = true;
this.row.request.name = this.row.id; this.row.request.name = this.row.id;
this.row.request.useEnvironment = this.environment.id; this.row.request.useEnvironment = this.environment;
this.runData.push(this.row.request); this.runData.push(this.row.request);
/*触发执行操作*/ /*触发执行操作*/
let testPlan = new TestPlan(); let testPlan = new TestPlan();
@ -71,18 +71,21 @@
this.runData.forEach(item => { this.runData.forEach(item => {
threadGroup.hashTree.push(item); threadGroup.hashTree.push(item);
}) })
let reqObj = {id: this.row.id, let reqObj = {
id: this.row.id,
testElement: testPlan, testElement: testPlan,
type: this.type, type: this.type,
name:this.row.name, name: this.row.name,
projectId:getCurrentProjectID(), projectId: getCurrentProjectID(),
environmentMap: new Map([
[getCurrentProjectID(), this.environment.id]
]),
}; };
let bodyFiles = getBodyUploadFiles(reqObj, this.runData); let bodyFiles = getBodyUploadFiles(reqObj, this.runData);
reqObj.reportId = "run"; reqObj.reportId = "run";
// let url = "/api/genPerformanceTest"; // let url = "/api/genPerformanceTest";
let url = "/api/genPerformanceTestXml"; let url = "/api/genPerformanceTestXml";
this.$fileUpload(url, null, bodyFiles, reqObj, response => { this.$fileUpload(url, null, bodyFiles, reqObj, response => {
let jmxObj = {}; let jmxObj = {};
jmxObj.name = response.data.name; jmxObj.name = response.data.name;
@ -97,12 +100,6 @@
this.$router.push({ this.$router.push({
path: "/performance/test/create" path: "/performance/test/create"
}) })
// let performanceId = response.data;
// if(performanceId!=null){
// this.$router.push({
// path: "/performance/test/edit/"+performanceId,
// })
// }
}, erro => { }, erro => {
this.$emit('runRefresh', {}); this.$emit('runRefresh', {});
}); });

View File

@ -22,7 +22,7 @@
<el-button type="primary" v-else style="float: right" size="mini" @click="update">{{$t('commons.update')}}</el-button> <el-button type="primary" v-else style="float: right" size="mini" @click="update">{{$t('commons.update')}}</el-button>
<div v-if="condition.type === 'MODULE'"> <div v-if="condition.type === 'MODULE'">
<ms-select-tree size="small" :data="moduleOptions" :default-key="condition.ids" @getValue="setModule" :obj="moduleObj" clearable checkStrictly multiple/> <ms-select-tree size="small" :data="moduleOptions" :default-key="condition.ids" @getValue="setModule" :obj="moduleObj" clearable checkStrictly multiple v-if="!loading"/>
</div> </div>
<div v-if="condition.type === 'PATH'"> <div v-if="condition.type === 'PATH'">
<el-input v-model="pathDetails.name" :placeholder="$t('api_test.value')" clearable size="small"> <el-input v-model="pathDetails.name" :placeholder="$t('api_test.value')" clearable size="small">
@ -36,7 +36,7 @@
</div> </div>
</el-form-item> </el-form-item>
<div class="ms-border"> <div class="ms-border">
<el-table :data="httpConfig.conditions" highlight-current-row @current-change="selectRow"> <el-table :data="httpConfig.conditions" highlight-current-row @current-change="selectRow" v-if="!loading">
<el-table-column prop="socket" :label="$t('load_test.domain')" width="180"> <el-table-column prop="socket" :label="$t('load_test.domain')" width="180">
<template v-slot:default="{row}"> <template v-slot:default="{row}">
{{getUrl(row)}} {{getUrl(row)}}
@ -110,6 +110,7 @@
id: "id", id: "id",
label: "name", label: "name",
}, },
loading: false,
pathDetails: new KeyValue({name: "", value: "contains"}), pathDetails: new KeyValue({name: "", value: "contains"}),
condition: {type: "NONE", details: [new KeyValue({name: "", value: "contains"})], protocol: "http", socket: "", domain: "", port: 0}, condition: {type: "NONE", details: [new KeyValue({name: "", value: "contains"})], protocol: "http", socket: "", domain: "", port: 0},
}; };
@ -165,13 +166,14 @@
} }
}, },
selectRow(row) { selectRow(row) {
this.condition = {};
if (row) { if (row) {
this.httpConfig.socket = row.socket; this.httpConfig.socket = row.socket;
this.httpConfig.protocol = row.protocol; this.httpConfig.protocol = row.protocol;
this.httpConfig.port = row.port; this.httpConfig.port = row.port;
this.condition = row; this.condition = row;
if (row.type === "PATH" && row.details.length > 0) { if (row.type === "PATH" && row.details.length > 0) {
this.pathDetails = row.details[0]; this.pathDetails = JSON.parse(JSON.stringify(row.details[0]));
} else if (row.type === "MODULE" && row.details.length > 0) { } else if (row.type === "MODULE" && row.details.length > 0) {
this.condition.ids = []; this.condition.ids = [];
row.details.forEach((item) => { row.details.forEach((item) => {
@ -179,6 +181,7 @@
}); });
} }
} }
this.reload();
}, },
typeChange() { typeChange() {
switch (this.condition.type) { switch (this.condition.type) {
@ -194,7 +197,7 @@
} }
}, },
list() { list() {
let url = "/api/automation/module/list/" + this.projectId; let url = "/api/module/list/" + this.projectId + "/HTTP";
this.result = this.$get(url, (response) => { this.result = this.$get(url, (response) => {
if (response.data !== undefined && response.data !== null) { if (response.data !== undefined && response.data !== null) {
this.moduleOptions = response.data; this.moduleOptions = response.data;
@ -216,11 +219,21 @@
id: this.condition.id, type: this.condition.type, domain: this.condition.domain, socket: this.condition.socket, id: this.condition.id, type: this.condition.type, domain: this.condition.domain, socket: this.condition.socket,
protocol: this.condition.protocol, details: this.condition.details, port: this.condition.port, time: this.condition.time protocol: this.condition.protocol, details: this.condition.details, port: this.condition.port, time: this.condition.time
}; };
if (obj.type === "PATH") {
this.httpConfig.conditions[index].details = [this.pathDetails];
}
if (index !== -1) { if (index !== -1) {
Vue.set(this.httpConfig.conditions[index], obj, 1); Vue.set(this.httpConfig.conditions[index], obj, 1);
this.condition = {type: "NONE", details: [new KeyValue({name: "", value: "contains"})], protocol: "", socket: "", domain: ""}; this.condition = {type: "NONE", details: [new KeyValue({name: "", value: "contains"})], protocol: "", socket: "", domain: ""};
this.reload();
} }
}, },
reload() {
this.loading = true
this.$nextTick(() => {
this.loading = false
});
},
add() { add() {
let obj = { let obj = {
id: getUUID(), type: this.condition.type, socket: this.condition.socket, protocol: this.condition.protocol, id: getUUID(), type: this.condition.type, socket: this.condition.socket, protocol: this.condition.protocol,
@ -243,9 +256,9 @@
}, },
copy(row) { copy(row) {
const index = this.httpConfig.conditions.findIndex((d) => d.id === row.id); const index = this.httpConfig.conditions.findIndex((d) => d.id === row.id);
let obj = {id: getUUID(), type: row.type, socket: row.socket, details: row.details, protocol: row.protocol, domain: row.domain,}; let obj = {id: getUUID(), type: row.type, socket: row.socket, details: row.details, protocol: row.protocol, domain: row.domain, time: new Date().getTime()};
if (index != -1) { if (index != -1) {
this.httpConfig.conditions.splice(index + 1, 0, obj); this.httpConfig.conditions.splice(index, 0, obj);
} else { } else {
this.httpConfig.conditions.push(obj); this.httpConfig.conditions.push(obj);
} }

View File

@ -3,7 +3,7 @@
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px;"> <div v-for="pe in data" :key="pe.id" style="margin-left: 20px;">
<el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-top: 8px;width: 200px;" size="small"> <el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-top: 8px;width: 200px;" size="small">
<el-option v-for="(environment, index) in pe.envs" :key="index" <el-option v-for="(environment, index) in pe.envs" :key="index"
:label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')" :label="environment.name"
:value="environment.id"/> :value="environment.id"/>
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)"> <el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
{{ $t('api_test.environment.environment_config') }} {{ $t('api_test.environment.environment_config') }}