Merge remote-tracking branch 'origin/master'

This commit is contained in:
wenyann 2021-03-09 17:44:08 +08:00
commit 3e64e39631
7 changed files with 123 additions and 154 deletions

View File

@ -11,6 +11,7 @@ import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.base.domain.ApiScenario;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.Schedule;
import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager;
@ -102,12 +103,16 @@ public class ApiAutomationController {
@PostMapping(value = "/run")
public String run(@RequestBody RunScenarioRequest request) {
request.setExecuteType(ExecuteType.Completed.name());
request.setTriggerMode(ApiRunMode.SCENARIO.name());
request.setRunMode(ApiRunMode.SCENARIO.name());
return apiAutomationService.run(request);
}
@PostMapping(value = "/run/batch")
public String runBatch(@RequestBody RunScenarioRequest request) {
request.setExecuteType(ExecuteType.Saved.name());
request.setTriggerMode(ApiRunMode.SCENARIO.name());
request.setRunMode(ApiRunMode.SCENARIO.name());
return apiAutomationService.run(request);
}

View File

@ -96,7 +96,7 @@ public class MsAssertions extends MsTestElement {
assertion.setJsonValidationBool(true);
assertion.setExpectNull(false);
assertion.setInvert(false);
assertion.setIsRegex(false);
assertion.setIsRegex(true);
return assertion;
}

View File

@ -157,17 +157,6 @@ public class ApiAutomationService {
return request;
}
public List<String> selectIdsNotExistsInPlan(String projectId, String planId) {
return extApiScenarioMapper.selectIdsNotExistsInPlan(projectId, planId);
}
public void deleteByIds(List<String> nodeIds) {
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andApiScenarioModuleIdIn(nodeIds);
apiScenarioMapper.deleteByExample(example);
}
public void removeToGcByIds(List<String> nodeIds) {
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andApiScenarioModuleIdIn(nodeIds);
@ -347,7 +336,7 @@ public class ApiAutomationService {
}
public byte[] loadFileAsBytes(FileOperationRequest fileOperationRequest) {
File file = new File("/opt/metersphere/data/body/" + fileOperationRequest.getId() + "_" + fileOperationRequest.getName());
File file = new File(FileUtils.BODY_FILE_DIR + fileOperationRequest.getId() + "_" + fileOperationRequest.getName());
try (FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);) {
byte[] b = new byte[1000];
@ -362,7 +351,7 @@ public class ApiAutomationService {
return null;
}
public void createScenarioReport(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID) {
public APIScenarioReportResult createScenarioReport(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID) {
APIScenarioReportResult report = new APIScenarioReportResult();
report.setId(id);
report.setTestId(id);
@ -384,87 +373,54 @@ public class ApiAutomationService {
report.setProjectId(projectId);
report.setScenarioName(scenarioName);
report.setScenarioId(scenarioId);
apiScenarioReportMapper.insert(report);
return report;
}
/**
* 生成HashTree
*
* @param apiScenarios 场景
* @param request 请求参数
* @param reportIds 报告ID
* @return hashTree
*/
private HashTree generateHashTree(List<ApiScenarioWithBLOBs> apiScenarios, RunScenarioRequest request, List<String> reportIds) {
HashTree jmeterHashTree = new ListedHashTree();
private void parse(String scenarioDefinition, MsScenario scenario) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
try {
JSONObject element = JSON.parseObject(scenarioDefinition);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
new TypeReference<LinkedList<MsTestElement>>() {
});
scenario.setHashTree(elements);
}
if (element != null && StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
scenario.setVariables(variables);
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.error(e.getMessage());
}
}
private HashTree generateHashTree(ApiScenarioWithBLOBs item, String reportId, Map<String, String> planEnvMap) {
HashTree jmeterHashTree = new HashTree();
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
try {
boolean isFirst = true;
for (ApiScenarioWithBLOBs item : apiScenarios) {
if (item.getStepTotal() == null || item.getStepTotal() == 0) {
// 只有一个场景且没有测试步骤则提示
if (apiScenarios.size() == 1) {
MSException.throwException((item.getName() + "" + Translator.get("automation_exec_info")));
}
LogUtil.warn(item.getName() + "" + Translator.get("automation_exec_info"));
continue;
}
MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName());
group.setName(UUID.randomUUID().toString());
// 批量执行的结果直接存储为报告
if (isFirst) {
group.setName(request.getId());
isFirst = false;
}
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JSONObject element = JSON.parseObject(item.getScenarioDefinition());
MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class);
MsThreadGroup group = new MsThreadGroup();
group.setLabel(item.getName());
group.setName(reportId);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
new TypeReference<LinkedList<MsTestElement>>() {
});
scenario.setHashTree(elements);
}
if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
scenario.setVariables(variables);
}
group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>();
scenarios.add(scenario);
// 创建场景报告
if (reportIds != null) {
//如果是测试计划页面触发的执行方式生成报告时createScenarioReport第二个参数需要特殊处理
if (StringUtils.equals(request.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
String testPlanScenarioId = item.getId();
if (request.getScenarioTestPlanIdMap() != null && request.getScenarioTestPlanIdMap().containsKey(item.getId())) {
testPlanScenarioId = request.getScenarioTestPlanIdMap().get(item.getId());
// 获取场景用例单独的执行环境
TestPlanApiScenario planApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(testPlanScenarioId);
String environment = planApiScenario.getEnvironment();
if (StringUtils.isNotBlank(environment)) {
scenario.setEnvironmentMap(JSON.parseObject(environment, Map.class));
}
}
createScenarioReport(group.getName(), testPlanScenarioId, item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
} else {
createScenarioReport(group.getName(), item.getId(), item.getName(), request.getTriggerMode() == null ? ReportTriggerMode.MANUAL.name() : request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
}
reportIds.add(group.getName());
}
group.setHashTree(scenarios);
testPlan.getHashTree().add(group);
MsScenario scenario = JSONObject.parseObject(item.getScenarioDefinition(), MsScenario.class);
if (planEnvMap.size() > 0) {
scenario.setEnvironmentMap(planEnvMap);
}
parse(item.getScenarioDefinition(), scenario);
group.setEnableCookieShare(scenario.isEnableCookieShare());
LinkedList<MsTestElement> scenarios = new LinkedList<>();
scenarios.add(scenario);
group.setHashTree(scenarios);
testPlan.getHashTree().add(group);
} catch (Exception ex) {
MSException.throwException(ex.getMessage());
}
@ -482,27 +438,11 @@ public class ApiAutomationService {
config.setOperating(true);
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
JSONObject element = JSON.parseObject(apiScenario.getScenarioDefinition());
MsScenario scenario = JSONObject.parseObject(apiScenario.getScenarioDefinition(), MsScenario.class);
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
new TypeReference<LinkedList<MsTestElement>>() {
});
scenario.setHashTree(elements);
}
if (element != null && StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<ScenarioVariable>>() {
});
scenario.setVariables(variables);
}
if (scenario == null) {
return null;
}
parse(apiScenario.getScenarioDefinition(), scenario);
// 针对导入的jmx 处理
if (CollectionUtils.isNotEmpty(scenario.getHashTree()) && (scenario.getHashTree().get(0) instanceof MsJmeterElement)) {
scenario.toHashTree(jmeterHashTree, scenario.getHashTree(), config);
@ -533,26 +473,62 @@ public class ApiAutomationService {
* @return
*/
public String run(RunScenarioRequest request) {
ServiceUtils.getSelectAllIds(request, request.getCondition(),
(query) -> extApiScenarioMapper.selectIdsByQuery((ApiScenarioRequest) query));
List<String> ids = request.getIds();
//检查是否有正在执行中的情景
this.checkScenarioIsRunning(ids);
List<ApiScenarioWithBLOBs> apiScenarios = extApiScenarioMapper.selectIds(ids);
String runMode = ApiRunMode.SCENARIO.name();
if (StringUtils.isNotBlank(request.getRunMode()) && StringUtils.equals(request.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
runMode = ApiRunMode.SCENARIO_PLAN.name();
List<ApiScenarioWithBLOBs> apiScenarios = extApiScenarioMapper.selectIds(ids);
// 只有一个场景且没有测试步骤则提示
if (apiScenarios != null && apiScenarios.size() == 1 && (apiScenarios.get(0).getStepTotal() == null || apiScenarios.get(0).getStepTotal() == 0)) {
MSException.throwException((apiScenarios.get(0).getName() + "" + Translator.get("automation_exec_info")));
}
if (StringUtils.isNotBlank(request.getRunMode()) && StringUtils.equals(request.getRunMode(), ApiRunMode.DEFINITION.name())) {
runMode = ApiRunMode.DEFINITION.name();
if (StringUtils.isEmpty(request.getTriggerMode())) {
request.setTriggerMode(ReportTriggerMode.MANUAL.name());
}
// 调用执行方法
List<String> reportIds = new LinkedList<>();
HashTree hashTree = generateHashTree(apiScenarios, request, reportIds);
jMeterService.runDefinition(JSON.toJSONString(reportIds), hashTree, request.getReportId(), runMode);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiScenarioReportMapper batchMapper = sqlSession.getMapper(ApiScenarioReportMapper.class);
String reportId = request.getId();
// 按照场景执行
for (ApiScenarioWithBLOBs item : apiScenarios) {
if (item.getStepTotal() == null || item.getStepTotal() == 0) {
continue;
}
APIScenarioReportResult report;
Map<String, String> planEnvMap = new HashMap<>();
//如果是测试计划页面触发的执行方式生成报告时createScenarioReport第二个参数需要特殊处理
if (StringUtils.equals(request.getRunMode(), ApiRunMode.SCENARIO_PLAN.name())) {
String testPlanScenarioId = item.getId();
if (request.getScenarioTestPlanIdMap() != null && request.getScenarioTestPlanIdMap().containsKey(item.getId())) {
testPlanScenarioId = request.getScenarioTestPlanIdMap().get(item.getId());
// 获取场景用例单独的执行环境
TestPlanApiScenario planApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(testPlanScenarioId);
String environment = planApiScenario.getEnvironment();
if (StringUtils.isNotBlank(environment)) {
planEnvMap = JSON.parseObject(environment, Map.class);
}
}
report = createScenarioReport(reportId, testPlanScenarioId, item.getName(), request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
} else {
report = createScenarioReport(reportId, item.getId(), item.getName(), request.getTriggerMode(),
request.getExecuteType(), item.getProjectId(), request.getReportUserID());
}
// 生成报告和HashTree
HashTree hashTree = generateHashTree(item, reportId, planEnvMap);
//存储报告
batchMapper.insert(report);
// 调用执行方法
jMeterService.runDefinition(report.getId(), hashTree, request.getReportId(), request.getRunMode());
// 重置报告ID
reportId = UUID.randomUUID().toString();
}
sqlSession.flushStatements();
return request.getId();
}
@ -598,7 +574,7 @@ public class ApiAutomationService {
public String debugRun(RunDefinitionRequest request, List<MultipartFile> bodyFiles) {
List<String> bodyUploadIds = new ArrayList<>(request.getBodyUploadIds());
FileUtils.createBodyFiles(bodyUploadIds, bodyFiles);
Map<String,EnvironmentConfig> envConfig = new HashMap<>();
Map<String, EnvironmentConfig> envConfig = new HashMap<>();
Map<String, String> map = request.getEnvironmentMap();
if (map != null) {
map.keySet().forEach(id -> {
@ -611,8 +587,9 @@ public class ApiAutomationService {
config.setConfig(envConfig);
HashTree hashTree = request.getTestElement().generateHashTree(config);
// 调用执行方法
createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
APIScenarioReportResult reportResult = createScenarioReport(request.getId(), request.getScenarioId(), request.getScenarioName(), ReportTriggerMode.MANUAL.name(), request.getExecuteType(), request.getProjectId(),
SessionUtils.getUserId());
apiScenarioReportMapper.insert(reportResult);
// 调用执行方法
jMeterService.runDefinition(request.getId(), hashTree, request.getReportId(), ApiRunMode.SCENARIO.name());
return request.getId();
@ -761,25 +738,14 @@ public class ApiAutomationService {
if (!apiScenarios.isEmpty()) {
testName = apiScenarios.get(0).getName();
}
if (CollectionUtils.isEmpty(apiScenarios)) {
return null;
}
MsTestPlan testPlan = new MsTestPlan();
testPlan.setHashTree(new LinkedList<>());
HashTree jmeterHashTree = generateHashTree(apiScenarios, request, null);
String jmx = testPlan.getJmx(jmeterHashTree);
jmx = apiTestService.updateJmxString(jmx, testName, true);
//将ThreadGroup的testname改为接口名称
// Document doc = DocumentHelper.parseText(jmx);// 获取可续保保单列表报文模板
// Element root = doc.getRootElement();
// Element rootHashTreeElement = root.element("hashTree");
// Element innerHashTreeElement = rootHashTreeElement.elements("hashTree").get(0);
// Element theadGroupElement = innerHashTreeElement.elements("ThreadGroup").get(0);
// theadGroupElement.attribute("testname").setText(testName);
// jmx = root.asXML();
String jmx = apiTestService.updateJmxString(generateJmx(apiScenarios.get(0)), testName, true);
String name = request.getName() + ".jmx";
JmxInfoDTO dto = new JmxInfoDTO();
dto.setName(name);
dto.setXml(jmx);
@ -943,7 +909,9 @@ public class ApiAutomationService {
Map<String, String> envMap = request.getEnvMap();
Map<String, List<String>> mapping = request.getMapping();
Set<String> set = mapping.keySet();
if (set.isEmpty()) { return; }
if (set.isEmpty()) {
return;
}
set.forEach(id -> {
Map<String, String> newEnvMap = new HashMap<>(16);
if (envMap != null && !envMap.isEmpty()) {

View File

@ -152,7 +152,7 @@ public class ApiScenarioReportService {
apiScenarioReportDetailMapper.insert(detail);
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(report.getScenarioId());
if(testPlanApiScenario!=null){
if (testPlanApiScenario != null) {
report.setScenarioId(testPlanApiScenario.getApiScenarioId());
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
if (scenarioResult.getError() > 0) {
@ -236,17 +236,12 @@ public class ApiScenarioReportService {
/**
* 批量更新状态防止重复刷新报告
*
* @param reportIds
* @param reportId
*/
private void updateScenarioStatus(String reportIds) {
if (StringUtils.isNotEmpty(reportIds)) {
private void updateScenarioStatus(String reportId) {
if (StringUtils.isNotEmpty(reportId)) {
List<String> list = new ArrayList<>();
try {
list = JSON.parseArray(reportIds, String.class);
} catch (Exception e) {
list.add(reportIds);
}
list.add(reportId);
ApiScenarioReportExample scenarioReportExample = new ApiScenarioReportExample();
scenarioReportExample.createCriteria().andIdIn(list);
List<ApiScenarioReport> reportList = apiScenarioReportMapper.selectByExample(scenarioReportExample);
@ -350,13 +345,13 @@ public class ApiScenarioReportService {
int handleCount = 7000;
//每次处理的集合
List<String> handleIdList = new ArrayList<>(handleCount);
while (ids.size() > handleCount){
while (ids.size() > handleCount) {
handleIdList = new ArrayList<>(handleCount);
List<String> otherIdList = new ArrayList<>();
for (int index = 0;index < ids.size();index++){
if(index<handleCount){
for (int index = 0; index < ids.size(); index++) {
if (index < handleCount) {
handleIdList.add(ids.get(index));
}else{
} else {
otherIdList.add(ids.get(index));
}
}
@ -372,7 +367,7 @@ public class ApiScenarioReportService {
}
//处理最后剩余的数据
if(!ids.isEmpty()){
if (!ids.isEmpty()) {
ApiScenarioReportDetailExample detailExample = new ApiScenarioReportDetailExample();
detailExample.createCriteria().andReportIdIn(ids);
apiScenarioReportDetailMapper.deleteByExample(detailExample);
@ -417,9 +412,9 @@ public class ApiScenarioReportService {
}
public List<ApiScenarioReport> selectLastReportByIds(List<String> ids) {
if(!ids.isEmpty()){
if (!ids.isEmpty()) {
return extApiScenarioReportMapper.selectLastReportByIds(ids);
}else {
} else {
return new ArrayList<>(0);
}
}

@ -1 +1 @@
Subproject commit 3f497f88ebbd312a3b7637c1b694a8e28c68c287
Subproject commit d2fc4b42117be97c679b4d15d6f979923e598f7f

@ -1 +1 @@
Subproject commit 62ca85d34fdb89663cce69c9c694cf368e7bb3e6
Subproject commit 360d7214d15951ae11b3973add795305a5c3d035

View File

@ -187,7 +187,7 @@ export default {
<style scoped>
.container {
width: 1440px;
width: 1200px;
height: 810px;
margin: calc((100vh - 810px) / 2) auto 0;
background-color: #FFFFFF;
@ -294,6 +294,7 @@ body {
color: #2B415C;
-webkit-font-smoothing: antialiased;
margin: 0;
height: auto;
}
.form .el-input > .el-input__inner {