refactor(接口测试): 导入jmx文件优化,支持多线程组
--story=1011083 --user=赵勇 【Bug转需求】接口自动化支持导入多线程的jmx文件 https://www.tapd.cn/55049933/s/1329318
This commit is contained in:
parent
273d8113b6
commit
a2a2bd0571
|
@ -29,6 +29,7 @@ import io.metersphere.api.dto.definition.request.sampler.dubbo.MsConsumerAndServ
|
||||||
import io.metersphere.api.dto.definition.request.sampler.dubbo.MsRegistryCenter;
|
import io.metersphere.api.dto.definition.request.sampler.dubbo.MsRegistryCenter;
|
||||||
import io.metersphere.api.dto.definition.request.timer.MsConstantTimer;
|
import io.metersphere.api.dto.definition.request.timer.MsConstantTimer;
|
||||||
import io.metersphere.api.dto.definition.request.unknown.MsJmeterElement;
|
import io.metersphere.api.dto.definition.request.unknown.MsJmeterElement;
|
||||||
|
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
|
||||||
import io.metersphere.api.dto.scenario.Body;
|
import io.metersphere.api.dto.scenario.Body;
|
||||||
import io.metersphere.api.dto.scenario.DatabaseConfig;
|
import io.metersphere.api.dto.scenario.DatabaseConfig;
|
||||||
import io.metersphere.api.dto.scenario.KeyValue;
|
import io.metersphere.api.dto.scenario.KeyValue;
|
||||||
|
@ -37,10 +38,7 @@ import io.metersphere.api.parse.ApiImportAbstractParser;
|
||||||
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||||
import io.metersphere.base.domain.ApiTestEnvironmentExample;
|
import io.metersphere.base.domain.ApiTestEnvironmentExample;
|
||||||
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
|
||||||
import io.metersphere.commons.constants.ElementConstants;
|
import io.metersphere.commons.constants.*;
|
||||||
import io.metersphere.commons.constants.LoopConstants;
|
|
||||||
import io.metersphere.commons.constants.PropertyConstant;
|
|
||||||
import io.metersphere.commons.constants.RequestTypeConstants;
|
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.utils.*;
|
import io.metersphere.commons.utils.*;
|
||||||
import io.metersphere.environment.service.BaseEnvironmentService;
|
import io.metersphere.environment.service.BaseEnvironmentService;
|
||||||
|
@ -48,8 +46,10 @@ import io.metersphere.plugin.core.MsTestElement;
|
||||||
import io.metersphere.request.BodyFile;
|
import io.metersphere.request.BodyFile;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.collections.MapUtils;
|
import org.apache.commons.collections.MapUtils;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jmeter.assertions.*;
|
import org.apache.jmeter.assertions.*;
|
||||||
|
import org.apache.jmeter.config.Argument;
|
||||||
import org.apache.jmeter.config.ConfigTestElement;
|
import org.apache.jmeter.config.ConfigTestElement;
|
||||||
import org.apache.jmeter.control.ForeachController;
|
import org.apache.jmeter.control.ForeachController;
|
||||||
import org.apache.jmeter.control.LoopController;
|
import org.apache.jmeter.control.LoopController;
|
||||||
|
@ -75,6 +75,7 @@ import org.apache.jmeter.save.SaveService;
|
||||||
import org.apache.jmeter.testelement.TestElement;
|
import org.apache.jmeter.testelement.TestElement;
|
||||||
import org.apache.jmeter.testelement.TestPlan;
|
import org.apache.jmeter.testelement.TestPlan;
|
||||||
import org.apache.jmeter.testelement.property.JMeterProperty;
|
import org.apache.jmeter.testelement.property.JMeterProperty;
|
||||||
|
import org.apache.jmeter.threads.ThreadGroup;
|
||||||
import org.apache.jmeter.timers.ConstantTimer;
|
import org.apache.jmeter.timers.ConstantTimer;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
|
||||||
|
@ -105,7 +106,27 @@ public class JMeterParser extends ApiImportAbstractParser<ScenarioImport> {
|
||||||
|
|
||||||
MsScenario scenario = new MsScenario();
|
MsScenario scenario = new MsScenario();
|
||||||
scenario.setReferenced("IMPORT");
|
scenario.setReferenced("IMPORT");
|
||||||
formatHashTree(testPlan, scenario);
|
|
||||||
|
TestPlan plan = (TestPlan) testPlan.getArray()[0];
|
||||||
|
if (plan.getArguments() != null) {
|
||||||
|
List<ScenarioVariable> variables = new LinkedList<>();
|
||||||
|
plan.getArguments().forEach(item -> {
|
||||||
|
ScenarioVariable scenarioVariable = new ScenarioVariable();
|
||||||
|
scenarioVariable.setId(UUID.randomUUID().toString());
|
||||||
|
scenarioVariable.setName(item.getName());
|
||||||
|
if (ObjectUtils.isNotEmpty(item.getObjectValue())) {
|
||||||
|
Argument arg = (Argument) item.getObjectValue();
|
||||||
|
scenarioVariable.setValue(arg.getValue());
|
||||||
|
}
|
||||||
|
scenarioVariable.setType(VariableTypeConstants.CONSTANT.name());
|
||||||
|
variables.add(scenarioVariable);
|
||||||
|
});
|
||||||
|
scenario.setVariables(variables);
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isEmpty(scenario.getHashTree())) {
|
||||||
|
scenario.setHashTree(new LinkedList<>());
|
||||||
|
}
|
||||||
|
formatHashTree(testPlan.getTree(plan), scenario);
|
||||||
this.projectId = request.getProjectId();
|
this.projectId = request.getProjectId();
|
||||||
ScenarioImport scenarioImport = new ScenarioImport();
|
ScenarioImport scenarioImport = new ScenarioImport();
|
||||||
scenarioImport.setData(parseObj(scenario, request));
|
scenarioImport.setData(parseObj(scenario, request));
|
||||||
|
@ -697,11 +718,7 @@ public class JMeterParser extends ApiImportAbstractParser<ScenarioImport> {
|
||||||
}
|
}
|
||||||
// 测试计划
|
// 测试计划
|
||||||
if (key instanceof TestPlan) {
|
if (key instanceof TestPlan) {
|
||||||
scenario.setName(((TestPlan) key).getName());
|
continue;
|
||||||
elementNode = new MsJmeterElement();
|
|
||||||
elementNode.setName(((TestPlan) key).getName());
|
|
||||||
((MsJmeterElement) elementNode).setJmeterElement(objToXml(key));
|
|
||||||
((MsJmeterElement) elementNode).setElementType(key.getClass().getSimpleName());
|
|
||||||
}
|
}
|
||||||
// 线程组
|
// 线程组
|
||||||
else if (key instanceof ThreadGroup) {
|
else if (key instanceof ThreadGroup) {
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2" class="ms-col-one ms-font">
|
<el-col :span="2" class="ms-col-one ms-font">
|
||||||
<el-link class="head" @click="showScenarioParameters"
|
<el-link class="head" @click="showScenarioParameters"
|
||||||
>{{ $t('api_test.automation.scenario_total') }}
|
>{{ $t('api_test.automation.scenario_total') }}
|
||||||
</el-link>
|
</el-link>
|
||||||
:{{ getVariableSize() }}
|
:{{ getVariableSize() }}
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -152,10 +152,10 @@
|
||||||
size="mini"
|
size="mini"
|
||||||
@command="handleCommand"
|
@command="handleCommand"
|
||||||
v-permission="[
|
v-permission="[
|
||||||
'PROJECT_API_SCENARIO:READ+EDIT',
|
'PROJECT_API_SCENARIO:READ+EDIT',
|
||||||
'PROJECT_API_SCENARIO:READ+CREATE',
|
'PROJECT_API_SCENARIO:READ+CREATE',
|
||||||
'PROJECT_API_SCENARIO:READ+COPY',
|
'PROJECT_API_SCENARIO:READ+COPY',
|
||||||
]">
|
]">
|
||||||
{{ $t('api_test.request.debug') }}
|
{{ $t('api_test.request.debug') }}
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item>{{ $t('api_test.automation.generate_report') }}</el-dropdown-item>
|
<el-dropdown-item>{{ $t('api_test.automation.generate_report') }}</el-dropdown-item>
|
||||||
|
@ -172,10 +172,10 @@
|
||||||
@click="editScenario"
|
@click="editScenario"
|
||||||
title="ctrl + s"
|
title="ctrl + s"
|
||||||
v-permission="[
|
v-permission="[
|
||||||
'PROJECT_API_SCENARIO:READ+EDIT',
|
'PROJECT_API_SCENARIO:READ+EDIT',
|
||||||
'PROJECT_API_SCENARIO:READ+CREATE',
|
'PROJECT_API_SCENARIO:READ+CREATE',
|
||||||
'PROJECT_API_SCENARIO:READ+COPY',
|
'PROJECT_API_SCENARIO:READ+COPY',
|
||||||
]">
|
]">
|
||||||
{{ $t('commons.save') }}
|
{{ $t('commons.save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
|
@ -196,26 +196,26 @@
|
||||||
<i
|
<i
|
||||||
class="el-icon-star-off"
|
class="el-icon-star-off"
|
||||||
style="
|
style="
|
||||||
color: var(--primary_color);
|
color: var(--primary_color);
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 3px;
|
top: 3px;
|
||||||
"
|
"
|
||||||
@click="saveFollow" />
|
@click="saveFollow" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip :content="$t('commons.cancel')" placement="bottom" effect="dark" v-show="showFollow">
|
<el-tooltip :content="$t('commons.cancel')" placement="bottom" effect="dark" v-show="showFollow">
|
||||||
<i
|
<i
|
||||||
class="el-icon-star-on"
|
class="el-icon-star-on"
|
||||||
style="
|
style="
|
||||||
color: var(--primary_color);
|
color: var(--primary_color);
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 3px;
|
top: 3px;
|
||||||
"
|
"
|
||||||
@click="saveFollow" />
|
@click="saveFollow" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-link
|
<el-link
|
||||||
|
@ -223,7 +223,7 @@
|
||||||
style="margin-right: 5px"
|
style="margin-right: 5px"
|
||||||
@click="openHis"
|
@click="openHis"
|
||||||
v-show="path === '/api/automation/update'"
|
v-show="path === '/api/automation/update'"
|
||||||
>{{ $t('operating_log.change_history') }}
|
>{{ $t('operating_log.change_history') }}
|
||||||
</el-link>
|
</el-link>
|
||||||
<!-- 版本历史 -->
|
<!-- 版本历史 -->
|
||||||
<mx-version-history
|
<mx-version-history
|
||||||
|
@ -258,8 +258,8 @@
|
||||||
<span class="ms-message-right">{{ $t('api_test.automation.request_total') }} {{ reqTotal }}</span>
|
<span class="ms-message-right">{{ $t('api_test.automation.request_total') }} {{ reqTotal }}</span>
|
||||||
<span class="ms-message-right">{{ $t('api_test.automation.request_success') }} {{ reqSuccess }}</span>
|
<span class="ms-message-right">{{ $t('api_test.automation.request_success') }} {{ reqSuccess }}</span>
|
||||||
<span class="ms-message-right">
|
<span class="ms-message-right">
|
||||||
{{ $t('api_test.automation.request_error') }}
|
{{ $t('api_test.automation.request_error') }}
|
||||||
{{ reqError }}</span
|
{{ reqError }}</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -293,65 +293,65 @@
|
||||||
align="middle"
|
align="middle"
|
||||||
slot-scope="{ node, data }"
|
slot-scope="{ node, data }"
|
||||||
style="width: 100%">
|
style="width: 100%">
|
||||||
<span
|
|
||||||
class="custom-tree-node-col"
|
|
||||||
style="padding-left: 0px; padding-right: 0px"
|
|
||||||
v-show="node && data.hashTree && data.hashTree.length > 0 && !data.isLeaf">
|
|
||||||
<span
|
<span
|
||||||
v-show="!node.expanded"
|
class="custom-tree-node-col"
|
||||||
class="el-icon-circle-plus-outline custom-node_e"
|
style="padding-left: 0px; padding-right: 0px"
|
||||||
@click="openOrClose(node, data)" />
|
v-show="node && data.hashTree && data.hashTree.length > 0 && !data.isLeaf">
|
||||||
<span
|
<span
|
||||||
v-show="node.expanded"
|
v-show="!node.expanded"
|
||||||
class="el-icon-remove-outline custom-node_e"
|
class="el-icon-circle-plus-outline custom-node_e"
|
||||||
@click="openOrClose(node, data)" />
|
@click="openOrClose(node, data)" />
|
||||||
</span>
|
<span
|
||||||
|
v-show="node.expanded"
|
||||||
|
class="el-icon-remove-outline custom-node_e"
|
||||||
|
@click="openOrClose(node, data)" />
|
||||||
|
</span>
|
||||||
<!-- 批量操作 -->
|
<!-- 批量操作 -->
|
||||||
<span
|
<span
|
||||||
:class="data.checkBox ? 'custom-tree-node-hide' : 'custom-tree-node-col'"
|
:class="data.checkBox ? 'custom-tree-node-hide' : 'custom-tree-node-col'"
|
||||||
style="padding-left: 0px; padding-right: 0px"
|
style="padding-left: 0px; padding-right: 0px"
|
||||||
v-show="(data.hashTree && data.hashTree.length === 0) || data.isLeaf">
|
v-show="(data.hashTree && data.hashTree.length === 0) || data.isLeaf">
|
||||||
<show-more-btn
|
<show-more-btn
|
||||||
:is-show="node.checked"
|
:is-show="node.checked"
|
||||||
:buttons="batchOperators"
|
:buttons="batchOperators"
|
||||||
:size="selectDataCounts"
|
:size="selectDataCounts"
|
||||||
v-show="data.checkBox"
|
v-show="data.checkBox"
|
||||||
style="margin-right: 10px" />
|
style="margin-right: 10px" />
|
||||||
</span>
|
</span>
|
||||||
<span style="width: calc(100% - 40px)">
|
<span style="width: calc(100% - 40px)">
|
||||||
<!-- 步骤组件-->
|
<!-- 步骤组件-->
|
||||||
<ms-component-config
|
<ms-component-config
|
||||||
:scenario-definition="scenarioDefinition"
|
:scenario-definition="scenarioDefinition"
|
||||||
:message="message"
|
:message="message"
|
||||||
:type="data.type"
|
:type="data.type"
|
||||||
:scenario="data"
|
:scenario="data"
|
||||||
:response="response"
|
:response="response"
|
||||||
:currentScenario="currentScenario"
|
:currentScenario="currentScenario"
|
||||||
:node="node"
|
:node="node"
|
||||||
:project-list="projectList"
|
:project-list="projectList"
|
||||||
:env-map="projectEnvMap"
|
:env-map="projectEnvMap"
|
||||||
:env-group-id="envGroupId"
|
:env-group-id="envGroupId"
|
||||||
:environment-type="environmentType"
|
:environment-type="environmentType"
|
||||||
@remove="remove"
|
@remove="remove"
|
||||||
@copyRow="copyRow"
|
@copyRow="copyRow"
|
||||||
@suggestClick="suggestClick"
|
@suggestClick="suggestClick"
|
||||||
@refReload="refReload"
|
@refReload="refReload"
|
||||||
@runScenario="runDebug"
|
@runScenario="runDebug"
|
||||||
@stopScenario="stop"
|
@stopScenario="stop"
|
||||||
@setDomain="setDomain"
|
@setDomain="setDomain"
|
||||||
@openScenario="openScenario"
|
@openScenario="openScenario"
|
||||||
@editScenarioAdvance="editScenarioAdvance"
|
@editScenarioAdvance="editScenarioAdvance"
|
||||||
ref="componentConfig"
|
ref="componentConfig"
|
||||||
v-if="
|
v-if="
|
||||||
stepFilter.get('ALlSamplerStep').indexOf(data.type) === -1 ||
|
stepFilter.get('ALlSamplerStep').indexOf(data.type) === -1 ||
|
||||||
!node.parent ||
|
!node.parent ||
|
||||||
!node.parent.data ||
|
!node.parent.data ||
|
||||||
stepFilter.get('AllSamplerProxy').indexOf(node.parent.data.type) === -1
|
stepFilter.get('AllSamplerProxy').indexOf(node.parent.data.type) === -1
|
||||||
" />
|
" />
|
||||||
<div v-else class="el-tree-node is-hidden is-focusable is-leaf" style="display: none">
|
<div v-else class="el-tree-node is-hidden is-focusable is-leaf" style="display: none">
|
||||||
{{ hideNode(node) }}
|
{{ hideNode(node) }}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-tree>
|
</el-tree>
|
||||||
</div>
|
</div>
|
||||||
|
@ -576,12 +576,11 @@ import {
|
||||||
saveScenario,
|
saveScenario,
|
||||||
} from '@/business/automation/api-automation';
|
} from '@/business/automation/api-automation';
|
||||||
import MsComponentConfig from './component/ComponentConfig';
|
import MsComponentConfig from './component/ComponentConfig';
|
||||||
import {ENV_TYPE} from 'metersphere-frontend/src/utils/constants';
|
import { ENV_TYPE } from 'metersphere-frontend/src/utils/constants';
|
||||||
import {mergeRequestDocumentData} from '@/business/definition/api-definition';
|
import { mergeRequestDocumentData } from '@/business/definition/api-definition';
|
||||||
import {getEnvironmentByProjectId} from 'metersphere-frontend/src/api/environment';
|
import { getEnvironmentByProjectId } from 'metersphere-frontend/src/api/environment';
|
||||||
import {useApiStore} from '@/store';
|
import { useApiStore } from '@/store';
|
||||||
import {getDefaultVersion, setLatestVersionById} from 'metersphere-frontend/src/api/version';
|
import { getDefaultVersion, setLatestVersionById } from 'metersphere-frontend/src/api/version';
|
||||||
|
|
||||||
|
|
||||||
const store = useApiStore();
|
const store = useApiStore();
|
||||||
|
|
||||||
|
@ -790,7 +789,7 @@ export default {
|
||||||
debugReportId: '',
|
debugReportId: '',
|
||||||
isPreventReClick: false,
|
isPreventReClick: false,
|
||||||
latestVersionId: '',
|
latestVersionId: '',
|
||||||
hasLatest: false
|
hasLatest: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -923,6 +922,9 @@ export default {
|
||||||
if (!array) {
|
if (!array) {
|
||||||
array = this.scenarioDefinition;
|
array = this.scenarioDefinition;
|
||||||
}
|
}
|
||||||
|
if (!array) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let isLeaf = true;
|
let isLeaf = true;
|
||||||
let nodeType = '';
|
let nodeType = '';
|
||||||
if (node) {
|
if (node) {
|
||||||
|
@ -2489,11 +2491,10 @@ export default {
|
||||||
if (!hasLicense()) {
|
if (!hasLicense()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
getDefaultVersion(this.projectId)
|
getDefaultVersion(this.projectId).then((response) => {
|
||||||
.then(response => {
|
this.latestVersionId = response.data;
|
||||||
this.latestVersionId = response.data;
|
this.getVersionHistory();
|
||||||
this.getVersionHistory();
|
});
|
||||||
});
|
|
||||||
},
|
},
|
||||||
getVersionHistory() {
|
getVersionHistory() {
|
||||||
if (!hasLicense()) {
|
if (!hasLicense()) {
|
||||||
|
@ -2507,7 +2508,7 @@ export default {
|
||||||
}
|
}
|
||||||
let latestVersionData = response.data.filter((v) => v.versionId === this.latestVersionId);
|
let latestVersionData = response.data.filter((v) => v.versionId === this.latestVersionId);
|
||||||
if (latestVersionData.length > 0) {
|
if (latestVersionData.length > 0) {
|
||||||
this.hasLatest = false
|
this.hasLatest = false;
|
||||||
} else {
|
} else {
|
||||||
this.hasLatest = true;
|
this.hasLatest = true;
|
||||||
}
|
}
|
||||||
|
@ -2567,8 +2568,8 @@ export default {
|
||||||
projectId: this.projectId,
|
projectId: this.projectId,
|
||||||
type: 'SCENARIO',
|
type: 'SCENARIO',
|
||||||
versionId: row.id,
|
versionId: row.id,
|
||||||
resourceId: this.currentScenario.id
|
resourceId: this.currentScenario.id,
|
||||||
}
|
};
|
||||||
setLatestVersionById(param).then(() => {
|
setLatestVersionById(param).then(() => {
|
||||||
this.$success(this.$t('commons.modify_success'));
|
this.$success(this.$t('commons.modify_success'));
|
||||||
this.checkout(row);
|
this.checkout(row);
|
||||||
|
|
Loading…
Reference in New Issue