fix(接口测试): 修复多层场景引用执行报告显示错误问题

This commit is contained in:
fit2-zhao 2022-01-04 17:31:32 +08:00 committed by fit2-zhao
parent 298eda34fe
commit c25ca33505
17 changed files with 69 additions and 115 deletions

View File

@ -1,16 +1,13 @@
package io.metersphere.api.controller;
import io.metersphere.api.dto.scenario.request.BodyFile;
import io.metersphere.api.jmeter.JmeterThreadUtils;
import io.metersphere.api.service.ApiJmeterFileService;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
@RestController
@ -25,18 +22,6 @@ public class ApiJmeterFileController {
return JmeterThreadUtils.stop(name);
}
@PostMapping("download/files")
public ResponseEntity<byte[]> downloadBodyFiles(@RequestBody List<BodyFile> bodyFileList) {
byte[] bytes = new byte[10];
if (CollectionUtils.isNotEmpty(bodyFileList)) {
bytes = apiJmeterFileService.downloadJmeterFiles(bodyFileList);
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + UUID.randomUUID().toString() + ".zip\"")
.body(bytes);
}
@GetMapping("download/jar")
public ResponseEntity<byte[]> downloadJmeterFiles() {
byte[] bytes = apiJmeterFileService.downloadJmeterJar();

View File

@ -14,6 +14,7 @@ public class StepTreeDTO {
private String resourceId;
private String label;
private RequestResult value;
private String allIndex;
//误报库编码
private String errorCode;

View File

@ -359,41 +359,6 @@ public class ElementUtil {
}
}
public static void dataFormatting(JSONArray hashTree, String id, String reportType) {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i);
formatSampler(element);
if (element != null && element.get("clazzName") == null && clazzMap.containsKey(element.getString("type"))) {
element.fluentPut("clazzName", clazzMap.get(element.getString("type")));
}
if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) {
if (element != null && requests.contains(element.getString("type")) && !element.getString("resourceId").contains(id)) {
element.fluentPut("resourceId", id + "=" + element.getString("resourceId"));
}
}
if (element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray, id, reportType);
}
}
}
public static void dataFormatting(JSONObject element, String id, String reportType) {
if (element != null && element.get("clazzName") == null && clazzMap.containsKey(element.getString("type"))) {
element.fluentPut("clazzName", clazzMap.get(element.getString("type")));
}
if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) {
if (element != null && requests.contains(element.getString("type")) && !element.getString("resourceId").contains(id)) {
element.fluentPut("resourceId", id + "=" + element.getString("resourceId"));
}
}
formatSampler(element);
if (element != null && element.containsKey("hashTree")) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray, id, reportType);
}
}
public static void dataSetDomain(JSONArray hashTree, MsParameter msParameter) {
try {
ObjectMapper mapper = new ObjectMapper();
@ -540,4 +505,11 @@ public class ElementUtil {
}
return null;
}
public static String getResourceId(String resourceId, ParameterConfig config, MsTestElement parent, String indexPath) {
if (StringUtils.isNotEmpty(config.getScenarioId()) && StringUtils.equals(config.getReportType(), RunModeConstants.SET_REPORT.toString())) {
resourceId = config.getScenarioId() + "=" + resourceId;
}
return resourceId + "_" + ElementUtil.getFullIndexPath(parent, indexPath);
}
}

View File

@ -52,6 +52,10 @@ public class ParameterConfig extends MsParameter {
*/
private String projectId;
private String scenarioId;
private String reportType;
private List<String> csvFilePaths = new ArrayList<>();

View File

@ -39,14 +39,14 @@ public class MsJSR223Processor extends MsTestElement {
public void toHashTree(HashTree tree, List<MsTestElement> hashTree, MsParameter msParameter) {
ParameterConfig config = (ParameterConfig) msParameter;
//替换Metersphere环境变量
if(StringUtils.isEmpty(this.getEnvironmentId())){
if(config.getConfig() != null){
if(config.getProjectId() != null){
if (StringUtils.isEmpty(this.getEnvironmentId())) {
if (config.getConfig() != null) {
if (config.getProjectId() != null) {
String evnId = config.getConfig().get(config.getProjectId()).getApiEnvironmentid();
this.setEnvironmentId(evnId);
}else {
} else {
Collection<EnvironmentConfig> evnConfigList = config.getConfig().values();
if(evnConfigList!=null && !evnConfigList.isEmpty()){
if (evnConfigList != null && !evnConfigList.isEmpty()) {
for (EnvironmentConfig configItem : evnConfigList) {
String evnId = configItem.getApiEnvironmentid();
this.setEnvironmentId(evnId);
@ -57,7 +57,7 @@ public class MsJSR223Processor extends MsTestElement {
}
}
script = StringUtils.replace(script, RunningParamKeys.API_ENVIRONMENT_ID,"\""+RunningParamKeys.RUNNING_PARAMS_PREFIX+this.getEnvironmentId()+".\"");
script = StringUtils.replace(script, RunningParamKeys.API_ENVIRONMENT_ID, "\"" + RunningParamKeys.RUNNING_PARAMS_PREFIX + this.getEnvironmentId() + ".\"");
// 非导出操作且不是启用状态则跳过执行
if (!config.isOperating() && !this.isEnable()) {
@ -71,14 +71,14 @@ public class MsJSR223Processor extends MsTestElement {
processor.setName("JSR223Processor");
}
processor.setProperty("MS-ID", this.getId());
processor.setProperty("MS-RESOURCE-ID", this.getResourceId()+ "_" + this.getIndex());
String indexPath = this.getIndex();
processor.setProperty("MS-RESOURCE-ID", ElementUtil.getResourceId(this.getResourceId(), config, this.getParent(), indexPath));
List<String> id_names = new LinkedList<>();
ElementUtil.getScenarioSet(this, id_names);
processor.setProperty("MS-SCENARIO", JSON.toJSONString(id_names));
processor.setProperty(TestElement.TEST_CLASS, JSR223Sampler.class.getName());
processor.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
/*processor.setProperty("cacheKey", "true");*/
processor.setProperty("scriptLanguage", this.getScriptLanguage());
if (StringUtils.isNotEmpty(this.getScriptLanguage()) && this.getScriptLanguage().equals("nashornScript")) {
processor.setProperty("scriptLanguage", "nashorn");

View File

@ -154,7 +154,7 @@ public class MsDubboSampler extends MsTestElement {
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("DubboSampleGui"));
sampler.setProperty("MS-ID", this.getId());
String indexPath = this.getIndex();
sampler.setProperty("MS-RESOURCE-ID", this.getResourceId() + "_" + ElementUtil.getFullIndexPath(this.getParent(), indexPath));
sampler.setProperty("MS-RESOURCE-ID", ElementUtil.getResourceId(this.getResourceId(), config, this.getParent(), indexPath));
List<String> id_names = new LinkedList<>();
ElementUtil.getScenarioSet(this, id_names);
sampler.setProperty("MS-SCENARIO", JSON.toJSONString(id_names));

View File

@ -200,7 +200,7 @@ public class MsHTTPSamplerProxy extends MsTestElement {
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("HttpTestSampleGui"));
sampler.setProperty("MS-ID", this.getId());
String indexPath = this.getIndex();
sampler.setProperty("MS-RESOURCE-ID", this.getResourceId() + "_" + ElementUtil.getFullIndexPath(this.getParent(), indexPath));
sampler.setProperty("MS-RESOURCE-ID", ElementUtil.getResourceId(this.getResourceId(), config, this.getParent(), indexPath));
List<String> id_names = new LinkedList<>();
ElementUtil.getScenarioSet(this, id_names);
sampler.setProperty("MS-SCENARIO", JSON.toJSONString(id_names));

View File

@ -302,7 +302,7 @@ public class MsJDBCSampler extends MsTestElement {
sampler.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("TestBeanGUI"));
sampler.setProperty("MS-ID", this.getId());
String indexPath = this.getIndex();
sampler.setProperty("MS-RESOURCE-ID", this.getResourceId() + "_" + ElementUtil.getFullIndexPath(this.getParent(), indexPath));
sampler.setProperty("MS-RESOURCE-ID", ElementUtil.getResourceId(this.getResourceId(), config, this.getParent(), indexPath));
List<String> id_names = new LinkedList<>();
ElementUtil.getScenarioSet(this, id_names);
sampler.setProperty("MS-SCENARIO", JSON.toJSONString(id_names));

View File

@ -20,7 +20,6 @@ import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.api.service.ApiTestCaseService;
import io.metersphere.base.domain.ApiDefinitionWithBLOBs;
import io.metersphere.base.domain.ApiTestCaseWithBLOBs;
import io.metersphere.commons.constants.DelimiterConstants;
import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.LogUtil;
@ -245,7 +244,7 @@ public class MsTCPSampler extends MsTestElement {
tcpSampler.setName(this.getName());
tcpSampler.setProperty("MS-ID", this.getId());
String indexPath = this.getIndex();
tcpSampler.setProperty("MS-RESOURCE-ID", this.getResourceId() + "_" + ElementUtil.getFullIndexPath(this.getParent(), indexPath));
tcpSampler.setProperty("MS-RESOURCE-ID", ElementUtil.getResourceId(this.getResourceId(), config, this.getParent(), indexPath));
List<String> id_names = new LinkedList<>();
ElementUtil.getScenarioSet(this, id_names);
tcpSampler.setProperty("MS-SCENARIO", JSON.toJSONString(id_names));

View File

@ -225,7 +225,7 @@ public class ApiScenarioEnvService {
}
String definition = apiScenarioWithBLOBs.getScenarioDefinition();
MsScenario scenario = JSONObject.parseObject(definition, MsScenario.class);
GenerateHashTreeUtil.parse(definition, scenario, apiScenarioWithBLOBs.getId(), null);
GenerateHashTreeUtil.parse(definition, scenario);
if (StringUtils.equals(environmentType, EnvironmentType.JSON.toString())) {
scenario.setEnvironmentMap(JSON.parseObject(environmentJson, Map.class));
} else if (StringUtils.equals(environmentType, EnvironmentType.GROUP.toString())) {

View File

@ -35,18 +35,18 @@ public class GenerateHashTreeUtil {
public static MsScenario parseScenarioDefinition(String scenarioDefinition) {
if (StringUtils.isNotEmpty(scenarioDefinition)) {
MsScenario scenario = JSONObject.parseObject(scenarioDefinition, MsScenario.class);
parse(scenarioDefinition, scenario, scenario.getId(), null);
parse(scenarioDefinition, scenario);
return scenario;
}
return null;
}
public static void parse(String scenarioDefinition, MsScenario scenario, String id, String reportType) {
public static void parse(String scenarioDefinition, MsScenario scenario) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
JSONObject element = JSON.parseObject(scenarioDefinition);
ElementUtil.dataFormatting(element, id, reportType);
ElementUtil.dataFormatting(element);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
@ -134,7 +134,7 @@ public class GenerateHashTreeUtil {
} else {
setScenarioEnv(scenario, item);
}
GenerateHashTreeUtil.parse(item.getScenarioDefinition(), scenario, item.getId(), reportType);
GenerateHashTreeUtil.parse(item.getScenarioDefinition(), scenario);
group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>();
@ -145,8 +145,10 @@ public class GenerateHashTreeUtil {
} catch (Exception ex) {
MSException.throwException(ex.getMessage());
}
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), new ParameterConfig());
ParameterConfig config = new ParameterConfig();
config.setScenarioId(item.getId());
config.setReportType(reportType);
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), config);
return jmeterHashTree;
}

View File

@ -721,7 +721,7 @@ public class ApiAutomationService {
if (scenario == null) {
return null;
}
GenerateHashTreeUtil.parse(apiScenario.getScenarioDefinition(), scenario, apiScenario.getId(), null);
GenerateHashTreeUtil.parse(apiScenario.getScenarioDefinition(), scenario);
String environmentType = apiScenario.getEnvironmentType();
String environmentJson = apiScenario.getEnvironmentJson();
String environmentGroupId = apiScenario.getEnvironmentGroupId();

View File

@ -47,18 +47,6 @@ public class ApiJmeterFileService {
@Resource
private EnvironmentGroupProjectService environmentGroupProjectService;
public byte[] downloadJmeterFiles(List<BodyFile> bodyFileList) {
Map<String, byte[]> files = new LinkedHashMap<>();
Map<String, byte[]> multipartFiles = this.getMultipartFiles(bodyFileList);
if (!com.alibaba.excel.util.CollectionUtils.isEmpty(multipartFiles)) {
for (String k : multipartFiles.keySet()) {
byte[] v = multipartFiles.get(k);
files.put(k, v);
}
}
return listBytesToZip(files);
}
public byte[] downloadJmeterFiles(String runMode, String remoteTestId, String reportId, String reportType, String queueId) {
Map<String, String> planEnvMap = new HashMap<>();
ApiScenarioWithBLOBs scenario = null;
@ -193,24 +181,7 @@ public class ApiJmeterFileService {
if (CollectionUtils.isNotEmpty(files)) {
for (BodyFile bodyFile : files) {
File file = new File(bodyFile.getName());
if (file != null && !file.exists()) {
byte[] fileByte = FileUtils.fileToByte(file);
if (fileByte != null) {
multipartFiles.put(file.getName(), fileByte);
}
}
}
}
return multipartFiles;
}
private Map<String, byte[]> getMultipartFiles(List<BodyFile> files) {
Map<String, byte[]> multipartFiles = new LinkedHashMap<>();
// 获取附件
if (CollectionUtils.isNotEmpty(files)) {
for (BodyFile bodyFile : files) {
File file = new File(bodyFile.getName());
if (file != null && !file.exists()) {
if (file != null && file.exists()) {
byte[] fileByte = FileUtils.fileToByte(file);
if (fileByte != null) {
multipartFiles.put(file.getName(), fileByte);
@ -229,7 +200,7 @@ public class ApiJmeterFileService {
files.put(fileName, jmx.getBytes(StandardCharsets.UTF_8));
// 获取JMX使用到的附件
Map<String, byte[]> multipartFiles = this.getMultipartFiles(hashTree);
if (!com.alibaba.excel.util.CollectionUtils.isEmpty(multipartFiles)) {
if (multipartFiles != null && !multipartFiles.isEmpty()) {
for (String k : multipartFiles.keySet()) {
byte[] v = multipartFiles.get(k);
files.put(k, v);

View File

@ -47,9 +47,6 @@ public class ApiScenarioReportResultService {
}
}
String resourceId = result.getResourceId();
if (StringUtils.isNotEmpty(resourceId) && resourceId.contains("_")) {
resourceId = StringUtils.substringBefore(result.getResourceId(), "_");
}
report.setResourceId(resourceId);
report.setReportId(reportId);
report.setTotalAssertions(Long.parseLong(result.getTotalAssertions() + ""));

View File

@ -362,7 +362,7 @@ public class ApiScenarioReportService {
public String getEnvironment(ApiScenarioWithBLOBs apiScenario) {
String environment = "未配置";
String environmentType = apiScenario.getEnvironmentType();
if (StringUtils.equals(environmentType, EnvironmentType.JSON.name())) {
if (StringUtils.equals(environmentType, EnvironmentType.JSON.name()) && StringUtils.isNotEmpty(apiScenario.getEnvironmentJson())) {
String environmentJson = apiScenario.getEnvironmentJson();
JSONObject jsonObject = JSON.parseObject(environmentJson);
ApiTestEnvironmentExample example = new ApiTestEnvironmentExample();

View File

@ -6,8 +6,11 @@ import com.alibaba.fastjson.JSONObject;
import io.metersphere.api.dto.ApiScenarioReportDTO;
import io.metersphere.api.dto.StepTreeDTO;
import io.metersphere.base.domain.*;
import io.metersphere.base.mapper.ApiScenarioMapper;
import io.metersphere.base.mapper.ApiScenarioReportResultMapper;
import io.metersphere.base.mapper.ApiScenarioReportStructureMapper;
import io.metersphere.commons.constants.MsTestElementConstants;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.constants.RunModeConstants;
import io.metersphere.dto.RequestResult;
import io.metersphere.utils.LoggerUtil;
@ -75,13 +78,23 @@ public class ApiScenarioReportStructureService {
JSONObject element = JSON.parseObject(apiScenario.getScenarioDefinition());
StepTreeDTO dto = null;
if (element != null && element.getBoolean("enable")) {
String referenced = element.getString("referenced");
if (StringUtils.equals(referenced, MsTestElementConstants.REF.name())) {
if (StringUtils.equals(element.getString("type"), "scenario")) {
ApiScenarioWithBLOBs scenarioWithBLOBs = CommonBeanFactory.getBean(ApiScenarioMapper.class).selectByPrimaryKey(element.getString("id"));
if (scenarioWithBLOBs != null) {
element = JSON.parseObject(scenarioWithBLOBs.getScenarioDefinition());
}
}
}
String resourceId = element.getString("resourceId");
if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) {
if (StringUtils.isNotEmpty(resourceId) && StringUtils.isNotEmpty(apiScenario.getId()) && !resourceId.contains(apiScenario.getId())) {
resourceId = apiScenario.getId() + "=" + element.getString("resourceId");
}
}
dto = new StepTreeDTO(apiScenario.getName(), resourceId, element.getString("type"), element.getIntValue("index"));
dto = new StepTreeDTO(apiScenario.getName(), resourceId, element.getString("type"), 1);
dto.setAllIndex(null);
if (element.containsKey("hashTree") && !requests.contains(dto.getType())) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");
dataFormatting(elementJSONArray, dto, apiScenario.getId(), reportType);
@ -94,6 +107,15 @@ public class ApiScenarioReportStructureService {
for (int i = 0; i < hashTree.size(); i++) {
JSONObject element = hashTree.getJSONObject(i);
if (element != null && element.getBoolean("enable")) {
String referenced = element.getString("referenced");
if (StringUtils.equals(referenced, MsTestElementConstants.REF.name())) {
if (StringUtils.equals(element.getString("type"), "scenario")) {
ApiScenarioWithBLOBs scenarioWithBLOBs = CommonBeanFactory.getBean(ApiScenarioMapper.class).selectByPrimaryKey(element.getString("id"));
if (scenarioWithBLOBs != null) {
element = JSON.parseObject(scenarioWithBLOBs.getScenarioDefinition());
}
}
}
String resourceId = element.getString("resourceId");
if (StringUtils.equals(reportType, RunModeConstants.SET_REPORT.toString())) {
if (StringUtils.isNotEmpty(resourceId) && StringUtils.isNotEmpty(id) && !resourceId.contains(id)) {
@ -101,6 +123,13 @@ public class ApiScenarioReportStructureService {
}
}
StepTreeDTO children = new StepTreeDTO(element.getString("name"), resourceId, element.getString("type"), element.getIntValue("index"));
if (StringUtils.isNotEmpty(dto.getAllIndex())) {
children.setAllIndex(dto.getAllIndex() + "_" + (children.getIndex() == 0 ? (i + 1) : children.getIndex()));
children.setResourceId(resourceId + "_" + children.getAllIndex());
} else {
children.setAllIndex("" + (children.getIndex() == 0 ? (i + 1) : children.getIndex()));
children.setResourceId(resourceId + "_" + children.getAllIndex());
}
dto.getChildren().add(children);
if (element.containsKey("hashTree") && !requests.contains(children.getType())) {
JSONArray elementJSONArray = element.getJSONArray("hashTree");

View File

@ -1,8 +1,6 @@
package io.metersphere.websocket;
import com.alibaba.fastjson.JSON;
import io.metersphere.api.dto.APIReportResult;
import io.metersphere.api.jmeter.TestResult;
import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.commons.utils.LogUtil;
import lombok.SneakyThrows;
@ -99,12 +97,8 @@ public class ApiReportWebSocket {
if (!session.isOpen()) {
return;
}
if (report != null) {
if (StringUtils.isNotEmpty(report.getContent())) {
session.getBasicRemote().sendText(report.getContent());
} else {
session.getBasicRemote().sendText(JSON.toJSONString(new TestResult()));
}
if (report != null && StringUtils.isNotEmpty(report.getContent())) {
session.getBasicRemote().sendText(report.getContent());
session.close();
}
} catch (Exception e) {