feat(接口测试): 场景变量支持启用自身场景变量优先策略
--story=1010745 --user=赵勇 场景嵌套引用的变量取值优化-接口场景 https://www.tapd.cn/55049933/s/1312907
This commit is contained in:
parent
00cb5c7343
commit
b5ca7416e9
|
@ -23,6 +23,7 @@ import io.metersphere.service.MsHashTreeService;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jmeter.config.Arguments;
|
import org.apache.jmeter.config.Arguments;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
|
@ -49,6 +50,7 @@ public class MsScenario extends MsTestElement {
|
||||||
private boolean environmentEnable;
|
private boolean environmentEnable;
|
||||||
private Boolean variableEnable;
|
private Boolean variableEnable;
|
||||||
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
|
private static final String BODY_FILE_DIR = FileUtils.BODY_FILE_DIR;
|
||||||
|
private Boolean mixEnable;
|
||||||
|
|
||||||
public MsScenario() {
|
public MsScenario() {
|
||||||
}
|
}
|
||||||
|
@ -112,12 +114,20 @@ public class MsScenario extends MsTestElement {
|
||||||
if (config != null && !config.getExcludeScenarioIds().contains(this.getId())) {
|
if (config != null && !config.getExcludeScenarioIds().contains(this.getId())) {
|
||||||
scenarioTree = MsCriticalSectionController.createHashTree(tree, this.getName(), this.isEnable());
|
scenarioTree = MsCriticalSectionController.createHashTree(tree, this.getName(), this.isEnable());
|
||||||
}
|
}
|
||||||
|
// 启用当前场景变量优先选择
|
||||||
|
if ((mixEnable == null || BooleanUtils.isTrue(mixEnable))
|
||||||
|
&& (this.variableEnable == null || BooleanUtils.isFalse(this.variableEnable))) {
|
||||||
|
config.margeVariables(this.variables, config.getTransferVariables());
|
||||||
|
}
|
||||||
// 环境变量
|
// 环境变量
|
||||||
Arguments arguments = ElementUtil.getConfigArguments(this.isEnvironmentEnable() ? newConfig : config, this.getName(), this.getProjectId(), this.getVariables());
|
Arguments arguments = ElementUtil.getConfigArguments(this.isEnvironmentEnable() ?
|
||||||
if (arguments != null && (this.variableEnable == null || this.variableEnable)) {
|
newConfig : config, this.getName(), this.getProjectId(), this.getVariables());
|
||||||
|
if (arguments != null && ((this.variableEnable == null || this.variableEnable)
|
||||||
|
|| (this.mixEnable == null || this.mixEnable))) {
|
||||||
Arguments valueSupposeMock = ParameterConfig.valueSupposeMock(arguments);
|
Arguments valueSupposeMock = ParameterConfig.valueSupposeMock(arguments);
|
||||||
// 这里加入自定义变量解决ForEach循环控制器取值问题,循环控制器无法从vars中取值
|
// 这里加入自定义变量解决ForEach循环控制器取值问题,循环控制器无法从vars中取值
|
||||||
if (this.variableEnable != null && this.variableEnable) {
|
if ((this.variableEnable == null || this.variableEnable)
|
||||||
|
|| (this.mixEnable == null || this.mixEnable)) {
|
||||||
scenarioTree.add(ElementUtil.argumentsToUserParameters(valueSupposeMock));
|
scenarioTree.add(ElementUtil.argumentsToUserParameters(valueSupposeMock));
|
||||||
} else {
|
} else {
|
||||||
scenarioTree.add(valueSupposeMock);
|
scenarioTree.add(valueSupposeMock);
|
||||||
|
|
|
@ -22,10 +22,12 @@ import io.metersphere.service.definition.ApiTestCaseService;
|
||||||
import io.metersphere.service.plan.TestPlanApiCaseService;
|
import io.metersphere.service.plan.TestPlanApiCaseService;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.jmeter.config.Arguments;
|
import org.apache.jmeter.config.Arguments;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class ParameterConfig extends MsParameter {
|
public class ParameterConfig extends MsParameter {
|
||||||
|
@ -222,4 +224,45 @@ public class ParameterConfig extends MsParameter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void margeVariables(List<ScenarioVariable> variables, List<ScenarioVariable> transferVariables) {
|
||||||
|
if (CollectionUtils.isNotEmpty(transferVariables)) {
|
||||||
|
List<ScenarioVariable> constants = variables.stream().filter(ScenarioVariable::isConstantValid).collect(Collectors.toList());
|
||||||
|
Map<String, List<ScenarioVariable>> transferVariableGroup =
|
||||||
|
transferVariables.stream().collect(Collectors.groupingBy(ScenarioVariable::getName, LinkedHashMap::new, Collectors.toList()));
|
||||||
|
Map<String, List<ScenarioVariable>> constantsGroup =
|
||||||
|
constants.stream().collect(Collectors.groupingBy(ScenarioVariable::getName, LinkedHashMap::new, Collectors.toList()));
|
||||||
|
// 更新相同名称的值
|
||||||
|
for (ScenarioVariable constant : constants) {
|
||||||
|
if (transferVariableGroup.containsKey(constant.getName())
|
||||||
|
&& CollectionUtils.isNotEmpty(transferVariableGroup.get(constant.getName()))) {
|
||||||
|
constant.setValue(transferVariableGroup.get(constant.getName()).get(0).getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 添加当前没有的值
|
||||||
|
transferVariables.forEach(item -> {
|
||||||
|
if (!constantsGroup.containsKey(item.getName())) {
|
||||||
|
variables.add(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void margeParentVariables(List<ScenarioVariable> variables, MsTestElement parent) {
|
||||||
|
// 取出父级场景且父场景不是顶级场景
|
||||||
|
MsScenario scenario = getScenario(parent);
|
||||||
|
if (scenario == null || BooleanUtils.isFalse(scenario.getMixEnable()) || CollectionUtils.isEmpty(scenario.getVariables())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.margeVariables(variables, scenario.getVariables());
|
||||||
|
}
|
||||||
|
|
||||||
|
private MsScenario getScenario(MsTestElement parent) {
|
||||||
|
if (parent != null && parent instanceof MsScenario) {
|
||||||
|
return parent.getParent() != null ? (MsScenario) parent : null;
|
||||||
|
} else if (parent != null && parent.getParent() != null) {
|
||||||
|
getScenario(parent.getParent());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,7 @@ public class MsHashTreeService {
|
||||||
public static final String NUM = "num";
|
public static final String NUM = "num";
|
||||||
public static final String ENV_ENABLE = "environmentEnable";
|
public static final String ENV_ENABLE = "environmentEnable";
|
||||||
public static final String VARIABLE_ENABLE = "variableEnable";
|
public static final String VARIABLE_ENABLE = "variableEnable";
|
||||||
|
public static final String MIX_ENABLE = "mixEnable";
|
||||||
public static final String DISABLED = "disabled";
|
public static final String DISABLED = "disabled";
|
||||||
public static final String VERSION_NAME = "versionName";
|
public static final String VERSION_NAME = "versionName";
|
||||||
public static final String VERSION_ENABLE = "versionEnable";
|
public static final String VERSION_ENABLE = "versionEnable";
|
||||||
|
@ -199,14 +200,17 @@ public class MsHashTreeService {
|
||||||
|
|
||||||
private JSONObject setRefScenario(JSONObject element) {
|
private JSONObject setRefScenario(JSONObject element) {
|
||||||
boolean enable = element.has(ENABLE) ? element.optBoolean(ENABLE) : true;
|
boolean enable = element.has(ENABLE) ? element.optBoolean(ENABLE) : true;
|
||||||
if (!element.has(VARIABLE_ENABLE)) {
|
if (!element.has(MIX_ENABLE)) {
|
||||||
element.put(VARIABLE_ENABLE, true);
|
element.put(MIX_ENABLE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(element.optString(ID));
|
ApiScenarioDTO scenarioWithBLOBs = extApiScenarioMapper.selectById(element.optString(ID));
|
||||||
if (scenarioWithBLOBs != null && StringUtils.isNotEmpty(scenarioWithBLOBs.getScenarioDefinition())) {
|
if (scenarioWithBLOBs != null && StringUtils.isNotEmpty(scenarioWithBLOBs.getScenarioDefinition())) {
|
||||||
boolean environmentEnable = element.has(ENV_ENABLE) ? element.optBoolean(ENV_ENABLE) : false;
|
boolean environmentEnable = element.has(ENV_ENABLE) ? element.optBoolean(ENV_ENABLE) : false;
|
||||||
boolean variableEnable = element.has(VARIABLE_ENABLE) ? element.optBoolean(VARIABLE_ENABLE) : true;
|
boolean variableEnable = element.has(VARIABLE_ENABLE) ? element.optBoolean(VARIABLE_ENABLE) : false;
|
||||||
|
boolean mixEnable = element.has(MIX_ENABLE)
|
||||||
|
? element.getBoolean(MIX_ENABLE) : true;
|
||||||
|
|
||||||
if (environmentEnable && StringUtils.isNotEmpty(scenarioWithBLOBs.getEnvironmentJson())) {
|
if (environmentEnable && StringUtils.isNotEmpty(scenarioWithBLOBs.getEnvironmentJson())) {
|
||||||
element.put(ENV_MAP, JSON.parseObject(scenarioWithBLOBs.getEnvironmentJson(), Map.class));
|
element.put(ENV_MAP, JSON.parseObject(scenarioWithBLOBs.getEnvironmentJson(), Map.class));
|
||||||
}
|
}
|
||||||
|
@ -220,6 +224,9 @@ public class MsHashTreeService {
|
||||||
if (!element.has(VARIABLE_ENABLE)) {
|
if (!element.has(VARIABLE_ENABLE)) {
|
||||||
element.put(VARIABLE_ENABLE, variableEnable);
|
element.put(VARIABLE_ENABLE, variableEnable);
|
||||||
}
|
}
|
||||||
|
if (!element.has(MIX_ENABLE) && !variableEnable) {
|
||||||
|
element.put(MIX_ENABLE, mixEnable);
|
||||||
|
}
|
||||||
//获取场景的当前项目是否开启了自定义id
|
//获取场景的当前项目是否开启了自定义id
|
||||||
ProjectConfig projectApplication = baseProjectApplicationService.getSpecificTypeValue(scenarioWithBLOBs.getProjectId(), "SCENARIO_CUSTOM_NUM");
|
ProjectConfig projectApplication = baseProjectApplicationService.getSpecificTypeValue(scenarioWithBLOBs.getProjectId(), "SCENARIO_CUSTOM_NUM");
|
||||||
element.put(SHOW_CUSTOM_NUM, projectApplication.getScenarioCustomNum());
|
element.put(SHOW_CUSTOM_NUM, projectApplication.getScenarioCustomNum());
|
||||||
|
|
|
@ -1524,7 +1524,7 @@ export default {
|
||||||
}
|
}
|
||||||
this.resetResourceId(item.hashTree, item.referenced);
|
this.resetResourceId(item.hashTree, item.referenced);
|
||||||
item.enable === undefined ? (item.enable = true) : item.enable;
|
item.enable === undefined ? (item.enable = true) : item.enable;
|
||||||
item.variableEnable = item.variableEnable === undefined ? true : item.variableEnable;
|
item.mixEnable = item.mixEnable === undefined && !item.variableEnable ? true : item.mixEnable;
|
||||||
if (this.selectedTreeNode) {
|
if (this.selectedTreeNode) {
|
||||||
if (this.stepFilter.get('SpecialSteps').indexOf(this.selectedTreeNode.type) !== -1) {
|
if (this.stepFilter.get('SpecialSteps').indexOf(this.selectedTreeNode.type) !== -1) {
|
||||||
this.scenarioDefinition.splice(this.selectedTreeNode.index, 0, item);
|
this.scenarioDefinition.splice(this.selectedTreeNode.index, 0, item);
|
||||||
|
|
|
@ -42,16 +42,22 @@
|
||||||
|
|
||||||
<ms-add-api-case :currentProtocol="currentProtocol" ref="apiCase" />
|
<ms-add-api-case :currentProtocol="currentProtocol" ref="apiCase" />
|
||||||
|
|
||||||
<el-dialog :title="$t('commons.reference_settings')" :visible.sync="dialogVisible" width="400px">
|
<el-dialog :title="$t('commons.reference_settings')" :visible.sync="dialogVisible" width="700px">
|
||||||
<ul>
|
<ul>
|
||||||
<el-tooltip :content="$t('commons.enable_scene_info')" placement="top" v-if="showEnableScenario">
|
<el-tooltip :content="$t('commons.enable_scene_info')" placement="top" v-if="showEnableScenario">
|
||||||
<el-checkbox v-model="data.environmentEnable" @change="checkEnv">
|
<el-checkbox v-model="data.environmentEnable" @change="checkEnv">
|
||||||
{{ $t('commons.enable_scene') }}
|
{{ $t('commons.enable_scene') }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-checkbox v-model="data.variableEnable">
|
<br />
|
||||||
|
|
||||||
|
<el-checkbox v-model="data.variableEnable" @change="variableChange">
|
||||||
{{ $t('commons.variable_scene') }}
|
{{ $t('commons.variable_scene') }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
|
<br />
|
||||||
|
<el-checkbox v-model="data.mixEnable" @change="mixChange">
|
||||||
|
{{ $t('api_case.mix_enable') }}
|
||||||
|
</el-checkbox>
|
||||||
</ul>
|
</ul>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,6 +106,16 @@ export default {
|
||||||
this.allSamplers = this.filter.get('DEFINITION');
|
this.allSamplers = this.filter.get('DEFINITION');
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
variableChange() {
|
||||||
|
if (this.data.variableEnable) {
|
||||||
|
this.data.mixEnable = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mixChange() {
|
||||||
|
if (this.data.mixEnable) {
|
||||||
|
this.data.variableEnable = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
handleCommand(cmd) {
|
handleCommand(cmd) {
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case 'copy':
|
case 'copy':
|
||||||
|
|
|
@ -5,6 +5,7 @@ import mf from 'metersphere-frontend/src/i18n/lang/en-US';
|
||||||
const message = {
|
const message = {
|
||||||
api_case: {
|
api_case: {
|
||||||
please_add_api_case: 'Please add api case',
|
please_add_api_case: 'Please add api case',
|
||||||
|
mix_enable: 'The current scene variable is used first, and the original scene variable is used if there is no',
|
||||||
},
|
},
|
||||||
api_definition: {
|
api_definition: {
|
||||||
debug_pool_warning:
|
debug_pool_warning:
|
||||||
|
|
|
@ -5,6 +5,7 @@ import mf from 'metersphere-frontend/src/i18n/lang/zh-CN';
|
||||||
const message = {
|
const message = {
|
||||||
api_case: {
|
api_case: {
|
||||||
please_add_api_case: '请先添加接口用例',
|
please_add_api_case: '请先添加接口用例',
|
||||||
|
mix_enable: '优先使用当前场景变量,没有则使用原场景变量',
|
||||||
},
|
},
|
||||||
api_definition: {
|
api_definition: {
|
||||||
debug_pool_warning: '调用资源池执行失败,请检查资源池是否配置正常',
|
debug_pool_warning: '调用资源池执行失败,请检查资源池是否配置正常',
|
||||||
|
|
|
@ -5,6 +5,7 @@ import mf from 'metersphere-frontend/src/i18n/lang/zh-TW';
|
||||||
const message = {
|
const message = {
|
||||||
api_case: {
|
api_case: {
|
||||||
please_add_api_case: '请先添加接口用例',
|
please_add_api_case: '请先添加接口用例',
|
||||||
|
mix_enable: '優先使用當前場景變量,沒有則使用原場景變量',
|
||||||
},
|
},
|
||||||
api_definition: {
|
api_definition: {
|
||||||
debug_pool_warning: '調用資源池執行失敗,請檢查資源池是否配置正常',
|
debug_pool_warning: '調用資源池執行失敗,請檢查資源池是否配置正常',
|
||||||
|
|
|
@ -60,7 +60,7 @@ export default {
|
||||||
return this.height ? (this.height + 'px') : (this.enableAutoHeight ? null : 'calc(100vh - 50px)')
|
return this.height ? (this.height + 'px') : (this.enableAutoHeight ? null : 'calc(100vh - 50px)')
|
||||||
},
|
},
|
||||||
containerCalHeight() {
|
containerCalHeight() {
|
||||||
return this.height ? (this.height - 30 + 'px') : (this.enableAutoHeight ? null : 'calc(100vh - 60px)')
|
return this.height ? (this.height - 30 + 'px') : (this.enableAutoHeight ? null : 'calc(100vh - 62px)')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|
|
@ -34,8 +34,8 @@ a:hover {
|
||||||
|
|
||||||
/* 滚动条样式 */
|
/* 滚动条样式 */
|
||||||
::-webkit-scrollbar{
|
::-webkit-scrollbar{
|
||||||
width: 10px;
|
width: 8px;
|
||||||
height: 10px;
|
height: 8px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
}
|
}
|
||||||
::-webkit-scrollbar-thumb{
|
::-webkit-scrollbar-thumb{
|
||||||
|
|
|
@ -197,8 +197,8 @@ textarea {
|
||||||
|
|
||||||
/* 滚动条样式 */
|
/* 滚动条样式 */
|
||||||
::-webkit-scrollbar{
|
::-webkit-scrollbar{
|
||||||
width: 10px;
|
width: 8px;
|
||||||
height: 10px;
|
height: 8px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
}
|
}
|
||||||
::-webkit-scrollbar-thumb{
|
::-webkit-scrollbar-thumb{
|
||||||
|
|
Loading…
Reference in New Issue