fix(全局前后置脚本): 修复全局前后置脚本每次请求都执行的问题

修复全局前后置脚本每次请求都执行的问题,并提供是否将前后置脚本的执行结果统计到场景执行记录的功能
This commit is contained in:
song-tianyang 2021-10-15 18:18:52 +08:00 committed by song-tianyang
parent 7de403fc49
commit 98de9231f6
9 changed files with 244 additions and 96 deletions

View File

@ -1,13 +1,25 @@
package io.metersphere.api.dto.definition.request;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONType;
import io.metersphere.api.dto.RunningParamKeys;
import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor;
import io.metersphere.api.dto.definition.request.sampler.MsDebugSampler;
import io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy;
import io.metersphere.api.dto.definition.request.sampler.MsJDBCSampler;
import io.metersphere.api.dto.definition.request.sampler.MsTCPSampler;
import io.metersphere.api.dto.mockconfig.MockConfigStaticData;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.service.ApiTestEnvironmentService;
import io.metersphere.base.domain.ApiTestEnvironmentWithBLOBs;
import io.metersphere.commons.constants.RunModeConstants;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.plugin.core.MsParameter;
import io.metersphere.plugin.core.MsTestElement;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.control.LoopController;
import org.apache.jmeter.protocol.http.control.CookieManager;
import org.apache.jmeter.save.SaveService;
@ -15,7 +27,9 @@ import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.threads.ThreadGroup;
import org.apache.jorphan.collections.HashTree;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@EqualsAndHashCode(callSuper = true)
@ -43,15 +57,157 @@ public class MsThreadGroup extends MsTestElement {
}
if (CollectionUtils.isNotEmpty(hashTree)) {
MsJSR223Processor preProcessor = null;
MsJSR223Processor postProcessor = null;
//获取projectConfig
String projectId = this.checkProjectId(hashTree);
this.checkEnviromentConfig(projectId,config,hashTree);
if (config.getConfig() != null) {
if (config.isEffective(projectId)) {
EnvironmentConfig environmentConfig = config.getConfig().get(projectId);
if (environmentConfig != null) {
preProcessor = environmentConfig.getPreProcessor();
postProcessor = environmentConfig.getPostProcessor();
}
}
}
//检查全局前后置脚本
if (preProcessor != null) {
preProcessor.setType("JSR223Processor");
preProcessor.setName("PRE_PROCESSOR_ENV_"+preProcessor.isConnScenario());
preProcessor.setClazzName("io.metersphere.api.dto.definition.request.processors.MsJSR223Processor");
preProcessor.toHashTree(groupTree, preProcessor.getHashTree(), config);
}
for (MsTestElement el : hashTree) {
el.toHashTree(groupTree, el.getHashTree(), config);
}
if (postProcessor != null) {
postProcessor.setType("JSR223Processor");
postProcessor.setName("POST_PROCESSOR_ENV_"+preProcessor.isConnScenario());
postProcessor.setClazzName("io.metersphere.api.dto.definition.request.processors.MsJSR223Processor");
postProcessor.toHashTree(groupTree, postProcessor.getHashTree(), config);
}
MsDebugSampler el = new MsDebugSampler();
el.setName(RunningParamKeys.RUNNING_DEBUG_SAMPLER_NAME);
el.toHashTree(groupTree, el.getHashTree(), config);
}
}
private String checkProjectId(List<MsTestElement> hashTree) {
String projectId = this.getProjectId();
if (StringUtils.isEmpty(projectId)) {
for (MsTestElement el : hashTree) {
if (el instanceof MsHTTPSamplerProxy) {
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) el;
projectId = httpSamplerProxy.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (el instanceof MsJDBCSampler) {
MsJDBCSampler jdbcSampler = (MsJDBCSampler) el;
projectId = jdbcSampler.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (el instanceof MsTCPSampler) {
MsTCPSampler tcpSampler = (MsTCPSampler) el;
projectId = tcpSampler.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (el instanceof MsScenario) {
MsScenario scenario = (MsScenario)el;
if(scenario.getHashTree() != null){
for (MsTestElement itemEl : scenario.getHashTree()) {
if (itemEl instanceof MsHTTPSamplerProxy) {
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) itemEl;
projectId = httpSamplerProxy.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (itemEl instanceof MsJDBCSampler) {
MsJDBCSampler jdbcSampler = (MsJDBCSampler) itemEl;
projectId = jdbcSampler.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
} else if (itemEl instanceof MsTCPSampler) {
MsTCPSampler tcpSampler = (MsTCPSampler) itemEl;
projectId = tcpSampler.getProjectId();
if (StringUtils.isNotEmpty(projectId)) {
break;
}
}
}
}
}
}
}
return projectId;
}
private void checkEnviromentConfig(String projectId, ParameterConfig config, List<MsTestElement> hashTree) {
//检查全局前后置脚本
if (config.getConfig() == null) {
// 单独接口执行
this.setProjectId(projectId);
String environmentId = null;
for (MsTestElement el : hashTree) {
if (el instanceof MsHTTPSamplerProxy) {
MsHTTPSamplerProxy httpSamplerProxy = (MsHTTPSamplerProxy) el;
environmentId = httpSamplerProxy.getUseEnvironment();
if (StringUtils.isNotEmpty(environmentId)) {
break;
}
} else if (el instanceof MsJDBCSampler) {
MsJDBCSampler jdbcSampler = (MsJDBCSampler) el;
environmentId = jdbcSampler.getEnvironmentId();
if (StringUtils.isNotEmpty(environmentId)) {
break;
}
} else if (el instanceof MsTCPSampler) {
MsTCPSampler tcpSampler = (MsTCPSampler) el;
environmentId = tcpSampler.getUseEnvironment();
if (StringUtils.isNotEmpty(environmentId)) {
break;
}
} else if (el instanceof MsScenario) {
Map<String, EnvironmentConfig> envConfig = new HashMap<>(16);
MsScenario scenario = (MsScenario)el;
// 兼容历史数据
if (scenario.getEnvironmentMap() == null || scenario.getEnvironmentMap().isEmpty()) {
scenario.setEnvironmentMap(new HashMap<>(16));
if (StringUtils.isNotBlank(environmentId)) {
// 兼容1.8之前 没有environmentMap但有environmentId的数据
scenario.getEnvironmentMap().put(RunModeConstants.HIS_PRO_ID.toString(), environmentId);
}
}
if (scenario.getEnvironmentMap() != null && !scenario.getEnvironmentMap().isEmpty()) {
scenario.getEnvironmentMap().keySet().forEach(itemProjectId -> {
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
ApiTestEnvironmentWithBLOBs environment = environmentService.get(scenario.getEnvironmentMap().get(itemProjectId));
if (environment != null && environment.getConfig() != null) {
EnvironmentConfig env = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
env.setApiEnvironmentid(environment.getId());
envConfig.put(itemProjectId, env);
if (StringUtils.equals(environment.getName(), MockConfigStaticData.MOCK_EVN_NAME)) {
this.setMockEnvironment(true);
}
}
});
config.setConfig(envConfig);
}
}
}
if (StringUtils.isNotEmpty(environmentId)) {
config.setConfig(ElementUtil.getEnvironmentConfig(environmentId, projectId, this.isMockEnvironment()));
}
}
}
public ThreadGroup getThreadGroup() {
LoopController loopController = new LoopController();
loopController.setName("LoopController");

View File

@ -36,6 +36,9 @@ public class MsJSR223Processor extends MsTestElement {
@JSONField(ordinal = 21)
private String scriptLanguage;
@JSONField(ordinal = 22)
private boolean connScenario = true;
@Override
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, MsParameter msParameter) {
ParameterConfig config = (ParameterConfig) msParameter;

View File

@ -175,7 +175,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
if (StringUtils.isEmpty(this.getEnvironmentId())) {
this.setEnvironmentId(this.useEnvironment);
}
// 非导出操作且不是启用状态则跳过执行
// 非导出操作且不是启用状态则跳过执行Ms
if (!config.isOperating() && !this.isEnable()) {
return;
}
@ -270,10 +270,6 @@ public class MsHTTPSamplerProxy extends MsTestElement {
addCertificate(config, httpSamplerTree);
//增加全局前后至脚本
if (httpConfig != null) {
this.setScript(httpConfig, httpSamplerTree, config);
}
if (CollectionUtils.isNotEmpty(hashTree)) {
for (MsTestElement el : hashTree) {
if (el.getEnvironmentId() == null) {
@ -288,32 +284,6 @@ public class MsHTTPSamplerProxy extends MsTestElement {
}
}
private void setScript(HttpConfig httpConfig, HashTree httpSamplerTree, ParameterConfig config) {
MsJSR223PreProcessor preProcessor = httpConfig.getPreProcessor();
MsJSR223PostProcessor postProcessor = httpConfig.getPostProcessor();
if (preProcessor != null && StringUtils.isNotEmpty(preProcessor.getScript())) {
if (preProcessor.getEnvironmentId() == null) {
if (this.getEnvironmentId() == null) {
preProcessor.setEnvironmentId(useEnvironment);
} else {
preProcessor.setEnvironmentId(this.getEnvironmentId());
}
}
preProcessor.toHashTree(httpSamplerTree, preProcessor.getHashTree(), config);
}
if (postProcessor != null && StringUtils.isNotEmpty(postProcessor.getScript())) {
if (postProcessor.getEnvironmentId() == null) {
if (this.getEnvironmentId() == null) {
postProcessor.setEnvironmentId(useEnvironment);
} else {
postProcessor.setEnvironmentId(this.getEnvironmentId());
}
}
postProcessor.toHashTree(httpSamplerTree, postProcessor.getHashTree(), config);
}
}
private void initConnectAndResponseTimeout(ParameterConfig config) {
if (config.isEffective(this.getProjectId())) {
String useEvnId = config.getConfig().get(this.getProjectId()).getApiEnvironmentid();
@ -358,8 +328,6 @@ public class MsHTTPSamplerProxy extends MsTestElement {
this.setEnvironmentId(useEvnId);
}
HttpConfig httpConfig = matchConfig(config);
httpConfig.setPreProcessor(environmentConfig.getPreProcessor());
httpConfig.setPostProcessor(environmentConfig.getPostProcessor());
return httpConfig;
}
}

View File

@ -149,34 +149,34 @@ public class MsJDBCSampler extends MsTestElement {
tree.add(arguments);
}
MsJSR223PreProcessor preProcessor = null;
MsJSR223PostProcessor postProcessor = null;
if(envConfig != null){
preProcessor = envConfig.getPreProcessor();
postProcessor = envConfig.getPostProcessor();
}
//增加全局前后至脚本
if(preProcessor != null){
if (preProcessor.getEnvironmentId() == null) {
if (this.getEnvironmentId() == null) {
preProcessor.setEnvironmentId(useEnvironment);
} else {
preProcessor.setEnvironmentId(this.getEnvironmentId());
}
}
preProcessor.toHashTree(samplerHashTree, preProcessor.getHashTree(), config);
}
if(postProcessor != null){
if (postProcessor.getEnvironmentId() == null) {
if (this.getEnvironmentId() == null) {
postProcessor.setEnvironmentId(useEnvironment);
} else {
postProcessor.setEnvironmentId(this.getEnvironmentId());
}
}
postProcessor.toHashTree(samplerHashTree, postProcessor.getHashTree(), config);
}
// MsJSR223PreProcessor preProcessor = null;
// MsJSR223PostProcessor postProcessor = null;
// if(envConfig != null){
// preProcessor = envConfig.getPreProcessor();
// postProcessor = envConfig.getPostProcessor();
// }
//
// //增加全局前后至脚本
// if(preProcessor != null){
// if (preProcessor.getEnvironmentId() == null) {
// if (this.getEnvironmentId() == null) {
// preProcessor.setEnvironmentId(useEnvironment);
// } else {
// preProcessor.setEnvironmentId(this.getEnvironmentId());
// }
// }
// preProcessor.toHashTree(samplerHashTree, preProcessor.getHashTree(), config);
// }
// if(postProcessor != null){
// if (postProcessor.getEnvironmentId() == null) {
// if (this.getEnvironmentId() == null) {
// postProcessor.setEnvironmentId(useEnvironment);
// } else {
// postProcessor.setEnvironmentId(this.getEnvironmentId());
// }
// }
// postProcessor.toHashTree(samplerHashTree, postProcessor.getHashTree(), config);
// }
if (CollectionUtils.isNotEmpty(hashTree)) {
hashTree.forEach(el -> {

View File

@ -148,33 +148,6 @@ public class MsTCPSampler extends MsTestElement {
samplerHashTree.add(tcpPreProcessor.getJSR223PreProcessor());
}
MsJSR223PreProcessor preProcessor = null;
MsJSR223PostProcessor postProcessor = null;
if(envConfig != null){
preProcessor = envConfig.getPreProcessor();
postProcessor = envConfig.getPostProcessor();
}
//增加全局前后至脚本
if(preProcessor != null){
if (preProcessor.getEnvironmentId() == null) {
if (this.getEnvironmentId() == null) {
preProcessor.setEnvironmentId(useEnvironment);
} else {
preProcessor.setEnvironmentId(this.getEnvironmentId());
}
}
preProcessor.toHashTree(samplerHashTree, preProcessor.getHashTree(), config);
}
if(postProcessor != null){
if (postProcessor.getEnvironmentId() == null) {
if (this.getEnvironmentId() == null) {
postProcessor.setEnvironmentId(useEnvironment);
} else {
postProcessor.setEnvironmentId(this.getEnvironmentId());
}
}
postProcessor.toHashTree(samplerHashTree, postProcessor.getHashTree(), config);
}
if (CollectionUtils.isNotEmpty(hashTree)) {
hashTree.forEach(el -> {
el.toHashTree(samplerHashTree, el.getHashTree(), config);

View File

@ -1,7 +1,5 @@
package io.metersphere.api.dto.scenario;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.base.domain.ApiModule;
import io.metersphere.base.domain.ApiModuleExample;
import io.metersphere.base.mapper.ApiModuleMapper;
@ -11,7 +9,6 @@ import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@ -26,9 +23,6 @@ public class HttpConfig {
private List<HttpConfigCondition> conditions;
private List<KeyValue> headers;
private MsJSR223PreProcessor preProcessor;
private MsJSR223PostProcessor postProcessor;
private ApiModuleMapper apiModuleMapper;
public HttpConfig initHttpConfig(HttpConfigCondition configCondition) {

View File

@ -1,6 +1,7 @@
package io.metersphere.api.dto.scenario.environment;
import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.definition.request.processors.MsJSR223Processor;
import io.metersphere.api.dto.definition.request.processors.post.MsJSR223PostProcessor;
import io.metersphere.api.dto.definition.request.processors.pre.MsJSR223PreProcessor;
import io.metersphere.api.dto.scenario.DatabaseConfig;
@ -20,8 +21,8 @@ public class EnvironmentConfig {
private List<DatabaseConfig> databaseConfigs;
private TCPConfig tcpConfig;
private KeyStoreConfig sslConfig;
private MsJSR223PostProcessor postProcessor;
private MsJSR223PreProcessor preProcessor;
private MsJSR223Processor postProcessor;
private MsJSR223Processor preProcessor;
private JSONObject authManager;
public EnvironmentConfig() {

View File

@ -100,6 +100,34 @@ public class TestResult {
* 场景里的第一层视为步骤不考虑深层情况
*/
if (result != null && CollectionUtils.isNotEmpty(result.getRequestResults())) {
//如果有全局前后置脚本会出现前后置的测试步骤影响统计此处略过不处理
// 同时jmeter会将前后置脚本步骤作为一个请求来计算当检测到有前后置脚本步骤执行时请求数也要做处理
List<RequestResult> formatedResult = new ArrayList<>();
int successStep = 0;
int errorStep = 0;
for (RequestResult item :result.getRequestResults()) {
if(!StringUtils.startsWithAny(item.getName(),"PRE_PROCESSOR_ENV_","POST_PROCESSOR_ENV_")){
formatedResult.add(item);
}else {
if(StringUtils.equalsAnyIgnoreCase(item.getName(),"PRE_PROCESSOR_ENV_false","POST_PROCESSOR_ENV_false")){
if(item.isSuccess()){
successStep++;
}else {
errorStep++;
}
}
}
}
result.setSuccess(result.getSuccess() - successStep);
result.setError(result.getError()-errorStep);
this.success = this.success - successStep;
this.error = this.error-errorStep;
this.total = this.total - successStep - errorStep;
result.setRequestResults(formatedResult);
result.getRequestResults().forEach(item -> {
String itemAndScenarioName = "";
if (StringUtils.isNotEmpty(item.getScenario())) {

View File

@ -27,12 +27,24 @@
<ms-environment-s-s-l-config :project-id="projectId" :ssl-config="environment.config.sslConfig" :is-read-only="isReadOnly"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.all_pre_script')" name="prescript">
<el-switch v-model="environment.config.preProcessor.connScenario" active-text="关联场景结果"
style="margin: 5px 5px 5px 5px"/>
<el-tooltip class="item" effect="dark" content="脚本步骤会统计到场景执行结果中,执行报错时会影响场景的最终执行结果" placement="right">
<i class="el-icon-info"/>
</el-tooltip>
<jsr233-processor-content v-if="isRefresh"
:jsr223-processor="environment.config.preProcessor"
:is-pre-processor="true"
:is-read-only="isReadOnly"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.definition.request.all_post_script')" name="postscript">
<el-switch v-model="environment.config.postProcessor.connScenario" active-text="关联场景结果"
style="margin: 5px 5px 5px 5px"/>
<el-tooltip class="item" effect="dark" content="脚本步骤会统计到场景执行结果中,执行报错时会影响场景的最终执行结果" placement="right">
<i class="el-icon-info"/>
</el-tooltip>
<jsr233-processor-content v-if="isRefresh"
:jsr223-processor="environment.config.postProcessor"
:is-pre-processor="false"
@ -111,15 +123,22 @@
if(!this.environment.config.preProcessor){
this.environment.config.preProcessor = createComponent("JSR223PreProcessor");
}
if(!this.environment.config.preProcessor.connScenario){
this.environment.config.preProcessor.connScenario = false;
}
if(!this.environment.config.postProcessor){
this.environment.config.postProcessor = createComponent("JSR223PostProcessor");
}
if(!this.environment.config.postProcessor.connScenario){
this.environment.config.postProcessor.connScenario = false;
}
if(!this.environment.config.authManager){
this.environment.config.authManager = {'hashTree':[]};
}
if(!this.environment.config.authManager.hashTree){
this.environment.config.authManager.hashTree = [];
}
},
watch: {
@ -136,6 +155,12 @@
this.environment.config.postProcessor.script = "";
}
}
if(!this.environment.config.preProcessor.connScenario){
this.environment.config.preProcessor.connScenario = false;
}
if(!this.environment.config.postProcessor.connScenario){
this.environment.config.postProcessor.connScenario = false;
}
if(!this.environment.config.authManager){
this.environment.config.authManager = {'hashTree':[]};