fix(测试计划): 修复测试计划用例批量执行问题
--bug=1007516 --user=赵勇 【测试计划】-批量并行+local资源池执行接口用例失败 https://www.tapd.cn/55049933/s/1059992
This commit is contained in:
parent
d8bf400e56
commit
d01e9d748f
|
@ -7,6 +7,7 @@ import io.metersphere.api.dto.automation.*;
|
||||||
import io.metersphere.api.dto.automation.parse.ScenarioImport;
|
import io.metersphere.api.dto.automation.parse.ScenarioImport;
|
||||||
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
import io.metersphere.api.dto.definition.RunDefinitionRequest;
|
||||||
import io.metersphere.api.jmeter.LocalRunner;
|
import io.metersphere.api.jmeter.LocalRunner;
|
||||||
|
import io.metersphere.api.jmeter.MessageCache;
|
||||||
import io.metersphere.api.service.ApiAutomationService;
|
import io.metersphere.api.service.ApiAutomationService;
|
||||||
import io.metersphere.base.domain.ApiScenario;
|
import io.metersphere.base.domain.ApiScenario;
|
||||||
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
|
||||||
|
@ -97,7 +98,7 @@ public class ApiAutomationController {
|
||||||
|
|
||||||
@PostMapping(value = "/create")
|
@PostMapping(value = "/create")
|
||||||
@MsAuditLog(module = "api_automation", type = OperLogConstants.CREATE, title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiAutomationService.class)
|
@MsAuditLog(module = "api_automation", type = OperLogConstants.CREATE, title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiAutomationService.class)
|
||||||
@RequiresPermissions(value={PermissionConstants.PROJECT_API_SCENARIO_READ_CREATE, PermissionConstants.PROJECT_API_SCENARIO_READ_COPY}, logical = Logical.OR)
|
@RequiresPermissions(value = {PermissionConstants.PROJECT_API_SCENARIO_READ_CREATE, PermissionConstants.PROJECT_API_SCENARIO_READ_COPY}, logical = Logical.OR)
|
||||||
@SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, event = NoticeConstants.Event.CREATE, mailTemplate = "api/AutomationCreate", subject = "接口自动化通知")
|
@SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, event = NoticeConstants.Event.CREATE, mailTemplate = "api/AutomationCreate", subject = "接口自动化通知")
|
||||||
public ApiScenario create(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "bodyFiles", required = false) List<MultipartFile> bodyFiles,
|
public ApiScenario create(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "bodyFiles", required = false) List<MultipartFile> bodyFiles,
|
||||||
@RequestPart(value = "scenarioFiles", required = false) List<MultipartFile> scenarioFiles) {
|
@RequestPart(value = "scenarioFiles", required = false) List<MultipartFile> scenarioFiles) {
|
||||||
|
@ -106,7 +107,7 @@ public class ApiAutomationController {
|
||||||
|
|
||||||
@PostMapping(value = "/update")
|
@PostMapping(value = "/update")
|
||||||
@MsAuditLog(module = "api_automation", type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiAutomationService.class)
|
@MsAuditLog(module = "api_automation", type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiAutomationService.class)
|
||||||
@RequiresPermissions(value={PermissionConstants.PROJECT_API_SCENARIO_READ_EDIT, PermissionConstants.PROJECT_API_SCENARIO_READ_COPY}, logical = Logical.OR)
|
@RequiresPermissions(value = {PermissionConstants.PROJECT_API_SCENARIO_READ_EDIT, PermissionConstants.PROJECT_API_SCENARIO_READ_COPY}, logical = Logical.OR)
|
||||||
@SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, event = NoticeConstants.Event.UPDATE, mailTemplate = "api/AutomationUpdate", subject = "接口自动化通知")
|
@SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, event = NoticeConstants.Event.UPDATE, mailTemplate = "api/AutomationUpdate", subject = "接口自动化通知")
|
||||||
public ApiScenario update(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "bodyFiles", required = false) List<MultipartFile> bodyFiles,
|
public ApiScenario update(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "bodyFiles", required = false) List<MultipartFile> bodyFiles,
|
||||||
@RequestPart(value = "scenarioFiles", required = false) List<MultipartFile> scenarioFiles) {
|
@RequestPart(value = "scenarioFiles", required = false) List<MultipartFile> scenarioFiles) {
|
||||||
|
@ -323,7 +324,10 @@ public class ApiAutomationController {
|
||||||
|
|
||||||
@GetMapping(value = "/stop/{reportId}")
|
@GetMapping(value = "/stop/{reportId}")
|
||||||
public void stop(@PathVariable String reportId) {
|
public void stop(@PathVariable String reportId) {
|
||||||
new LocalRunner().stop(reportId);
|
if (StringUtils.isNotEmpty(reportId)) {
|
||||||
|
MessageCache.batchTestCases.remove(reportId);
|
||||||
|
new LocalRunner().stop(reportId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/stop/batch")
|
@PostMapping(value = "/stop/batch")
|
||||||
|
|
|
@ -174,11 +174,6 @@ public class JMeterService {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
// SendResult result = kafkaTemplate.send(KafkaConfig.EXEC_TOPIC, JSON.toJSONString(runRequest)).get();
|
|
||||||
// if (result != null) {
|
|
||||||
// LogUtil.debug("获取ack 结果:" + result.getRecordMetadata());
|
|
||||||
// }
|
|
||||||
// kafkaTemplate.flush();
|
|
||||||
this.send(runRequest, config, reportId);
|
this.send(runRequest, config, reportId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -186,6 +181,7 @@ public class JMeterService {
|
||||||
&& MessageCache.cache.get(config.getAmassReport()).getReportIds() != null) {
|
&& MessageCache.cache.get(config.getAmassReport()).getReportIds() != null) {
|
||||||
MessageCache.cache.get(config.getAmassReport()).getReportIds().remove(reportId);
|
MessageCache.cache.get(config.getAmassReport()).getReportIds().remove(reportId);
|
||||||
}
|
}
|
||||||
|
MessageCache.batchTestCases.remove(reportId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,6 +212,7 @@ public class JMeterService {
|
||||||
&& MessageCache.cache.get(config.getAmassReport()).getReportIds() != null) {
|
&& MessageCache.cache.get(config.getAmassReport()).getReportIds() != null) {
|
||||||
MessageCache.cache.get(config.getAmassReport()).getReportIds().remove(reportId);
|
MessageCache.cache.get(config.getAmassReport()).getReportIds().remove(reportId);
|
||||||
}
|
}
|
||||||
|
MessageCache.batchTestCases.remove(reportId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,6 @@ import io.metersphere.track.service.TestPlanService;
|
||||||
import org.apache.commons.beanutils.BeanMap;
|
import org.apache.commons.beanutils.BeanMap;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.ibatis.session.ExecutorType;
|
|
||||||
import org.apache.ibatis.session.SqlSession;
|
|
||||||
import org.apache.ibatis.session.SqlSessionFactory;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
@ -73,7 +70,7 @@ public class ApiDefinitionExecResultService {
|
||||||
result.getScenarios().forEach(scenarioResult -> {
|
result.getScenarios().forEach(scenarioResult -> {
|
||||||
if (scenarioResult != null && CollectionUtils.isNotEmpty(scenarioResult.getRequestResults())) {
|
if (scenarioResult != null && CollectionUtils.isNotEmpty(scenarioResult.getRequestResults())) {
|
||||||
scenarioResult.getRequestResults().forEach(item -> {
|
scenarioResult.getRequestResults().forEach(item -> {
|
||||||
if(!StringUtils.startsWithAny(item.getName(),"PRE_PROCESSOR_ENV_","POST_PROCESSOR_ENV_")){
|
if (!StringUtils.startsWithAny(item.getName(), "PRE_PROCESSOR_ENV_", "POST_PROCESSOR_ENV_")) {
|
||||||
ApiDefinitionExecResult saveResult = MessageCache.batchTestCases.get(result.getTestId());
|
ApiDefinitionExecResult saveResult = MessageCache.batchTestCases.get(result.getTestId());
|
||||||
if (saveResult == null) {
|
if (saveResult == null) {
|
||||||
saveResult = apiDefinitionExecResultMapper.selectByPrimaryKey(result.getTestId());
|
saveResult = apiDefinitionExecResultMapper.selectByPrimaryKey(result.getTestId());
|
||||||
|
@ -96,10 +93,13 @@ public class ApiDefinitionExecResultService {
|
||||||
if (StringUtils.isNotEmpty(result.getUserId())) {
|
if (StringUtils.isNotEmpty(result.getUserId())) {
|
||||||
saveResult.setUserId(result.getUserId());
|
saveResult.setUserId(result.getUserId());
|
||||||
} else {
|
} else {
|
||||||
saveResult.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
|
if (SessionUtils.getUser() != null) {
|
||||||
|
saveResult.setUserId(SessionUtils.getUser().getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
saved = false;
|
saved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String status = item.isSuccess() ? "success" : "error";
|
String status = item.isSuccess() ? "success" : "error";
|
||||||
saveResult.setName(getName(type, item.getName(), status, saveResult.getCreateTime(), saveResult.getId()));
|
saveResult.setName(getName(type, item.getName(), status, saveResult.getCreateTime(), saveResult.getId()));
|
||||||
saveResult.setStatus(status);
|
saveResult.setStatus(status);
|
||||||
|
@ -124,6 +124,9 @@ public class ApiDefinitionExecResultService {
|
||||||
apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult);
|
apiDefinitionExecResultMapper.updateByPrimaryKeyWithBLOBs(saveResult);
|
||||||
}
|
}
|
||||||
apiDefinitionService.removeCache(result.getTestId());
|
apiDefinitionService.removeCache(result.getTestId());
|
||||||
|
if (StringUtils.isNotEmpty(result.getTestId())) {
|
||||||
|
MessageCache.batchTestCases.remove(result.getTestId());
|
||||||
|
}
|
||||||
// 发送通知
|
// 发送通知
|
||||||
sendNotice(saveResult);
|
sendNotice(saveResult);
|
||||||
}
|
}
|
||||||
|
|
|
@ -783,7 +783,8 @@ public class ApiTestCaseService {
|
||||||
batchMapper.insert(report);
|
batchMapper.insert(report);
|
||||||
executeQueue.add(runCaseRequest);
|
executeQueue.add(runCaseRequest);
|
||||||
}
|
}
|
||||||
sqlSession.flushStatements();
|
sqlSession.commit();
|
||||||
|
|
||||||
for (RunCaseRequest runCaseRequest : executeQueue) {
|
for (RunCaseRequest runCaseRequest : executeQueue) {
|
||||||
run(runCaseRequest);
|
run(runCaseRequest);
|
||||||
MessageCache.batchTestCases.put(runCaseRequest.getReportId(), runCaseRequest.getReport());
|
MessageCache.batchTestCases.put(runCaseRequest.getReportId(), runCaseRequest.getReport());
|
||||||
|
|
|
@ -108,6 +108,7 @@ public class TaskService {
|
||||||
result.setStatus("STOP");
|
result.setStatus("STOP");
|
||||||
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result);
|
apiDefinitionExecResultMapper.updateByPrimaryKeySelective(result);
|
||||||
actuator = result.getActuator();
|
actuator = result.getActuator();
|
||||||
|
MessageCache.batchTestCases.remove(result.getId());
|
||||||
}
|
}
|
||||||
} else if (StringUtils.equals(request.getType(), "SCENARIO")) {
|
} else if (StringUtils.equals(request.getType(), "SCENARIO")) {
|
||||||
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
|
ApiScenarioReport report = apiScenarioReportMapper.selectByPrimaryKey(request.getReportId());
|
||||||
|
|
|
@ -380,7 +380,9 @@ public class TestPlanApiCaseService {
|
||||||
if (request.getConfig() != null && StringUtils.isNotEmpty(request.getConfig().getResourcePoolId())) {
|
if (request.getConfig() != null && StringUtils.isNotEmpty(request.getConfig().getResourcePoolId())) {
|
||||||
apiResult.setActuator(request.getConfig().getResourcePoolId());
|
apiResult.setActuator(request.getConfig().getResourcePoolId());
|
||||||
}
|
}
|
||||||
apiResult.setUserId(Objects.requireNonNull(SessionUtils.getUser()).getId());
|
if (SessionUtils.getUser() != null) {
|
||||||
|
apiResult.setUserId(SessionUtils.getUser().getId());
|
||||||
|
}
|
||||||
apiResult.setResourceId(key.getApiCaseId());
|
apiResult.setResourceId(key.getApiCaseId());
|
||||||
apiResult.setStartTime(System.currentTimeMillis());
|
apiResult.setStartTime(System.currentTimeMillis());
|
||||||
apiResult.setType(ApiRunMode.API_PLAN.name());
|
apiResult.setType(ApiRunMode.API_PLAN.name());
|
||||||
|
@ -413,7 +415,7 @@ public class TestPlanApiCaseService {
|
||||||
ApiDefinitionExecResult report = addResult(request, testPlanApiCase, APITestStatus.Waiting.name(), batchMapper);
|
ApiDefinitionExecResult report = addResult(request, testPlanApiCase, APITestStatus.Waiting.name(), batchMapper);
|
||||||
executeQueue.put(testPlanApiCase, report);
|
executeQueue.put(testPlanApiCase, report);
|
||||||
});
|
});
|
||||||
sqlSession.flushStatements();
|
sqlSession.commit();
|
||||||
List<String> reportIds = new LinkedList<>();
|
List<String> reportIds = new LinkedList<>();
|
||||||
// 开始串行执行
|
// 开始串行执行
|
||||||
Thread thread = new Thread(new Runnable() {
|
Thread thread = new Thread(new Runnable() {
|
||||||
|
@ -421,7 +423,7 @@ public class TestPlanApiCaseService {
|
||||||
public void run() {
|
public void run() {
|
||||||
for (TestPlanApiCase testPlanApiCase : executeQueue.keySet()) {
|
for (TestPlanApiCase testPlanApiCase : executeQueue.keySet()) {
|
||||||
try {
|
try {
|
||||||
if (executeQueue.get(testPlanApiCase)!=null && MessageCache.terminationOrderDeque.contains(executeQueue.get(testPlanApiCase).getId())) {
|
if (executeQueue.get(testPlanApiCase) != null && MessageCache.terminationOrderDeque.contains(executeQueue.get(testPlanApiCase).getId())) {
|
||||||
MessageCache.terminationOrderDeque.remove(executeQueue.get(testPlanApiCase).getId());
|
MessageCache.terminationOrderDeque.remove(executeQueue.get(testPlanApiCase).getId());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -467,25 +469,23 @@ public class TestPlanApiCaseService {
|
||||||
});
|
});
|
||||||
thread.start();
|
thread.start();
|
||||||
} else {
|
} else {
|
||||||
|
Map<String, TestPlanApiCase> executeQueue = new HashMap<>();
|
||||||
|
planApiCases.forEach(testPlanApiCase -> {
|
||||||
|
ApiDefinitionExecResult report = addResult(request, testPlanApiCase, APITestStatus.Running.name(), batchMapper);
|
||||||
|
executeQueue.put(report.getId(), testPlanApiCase);
|
||||||
|
MessageCache.batchTestCases.put(report.getId(), report);
|
||||||
|
});
|
||||||
|
sqlSession.commit();
|
||||||
|
|
||||||
// 开始并发执行
|
// 开始并发执行
|
||||||
for (TestPlanApiCase key : planApiCases) {
|
for (String reportId : executeQueue.keySet()) {
|
||||||
RunModeDataDTO modeDataDTO = null;
|
|
||||||
if (StringUtils.isNotBlank(request.getConfig().getResourcePoolId())) {
|
|
||||||
modeDataDTO = new RunModeDataDTO(key.getId(), UUID.randomUUID().toString());
|
|
||||||
} else {
|
|
||||||
// 生成报告和HashTree
|
|
||||||
HashTree hashTree = generateHashTree(key.getId());
|
|
||||||
modeDataDTO = new RunModeDataDTO(hashTree, UUID.randomUUID().toString());
|
|
||||||
}
|
|
||||||
ApiDefinitionExecResult report = addResult(request, key, APITestStatus.Running.name(), batchMapper);
|
|
||||||
modeDataDTO.setApiCaseId(report.getId());
|
|
||||||
if (request.getConfig() != null && StringUtils.isNotEmpty(request.getConfig().getResourcePoolId())) {
|
if (request.getConfig() != null && StringUtils.isNotEmpty(request.getConfig().getResourcePoolId())) {
|
||||||
jMeterService.runTest(report.getId(), modeDataDTO.getApiCaseId(), ApiRunMode.API_PLAN.name(), null, request.getConfig());
|
jMeterService.runTest(executeQueue.get(reportId).getId(), reportId, ApiRunMode.API_PLAN.name(), null, request.getConfig());
|
||||||
} else {
|
} else {
|
||||||
jMeterService.runLocal(report.getId(), modeDataDTO.getHashTree(), TriggerMode.BATCH.name() , ApiRunMode.API_PLAN.name());
|
HashTree hashTree = generateHashTree(executeQueue.get(reportId).getId());
|
||||||
|
jMeterService.runLocal(reportId, hashTree, TriggerMode.BATCH.name(), ApiRunMode.API_PLAN.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlSession.flushStatements();
|
|
||||||
}
|
}
|
||||||
return request.getId();
|
return request.getId();
|
||||||
}
|
}
|
||||||
|
@ -566,7 +566,7 @@ public class TestPlanApiCaseService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ApiTestCaseWithBLOBs getApiTestCaseById(String testPlanApiCaseId) {
|
public ApiTestCaseWithBLOBs getApiTestCaseById(String testPlanApiCaseId) {
|
||||||
return extTestPlanApiCaseMapper.getApiTestCaseById(testPlanApiCaseId);
|
return extTestPlanApiCaseMapper.getApiTestCaseById(testPlanApiCaseId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void calculatePlanReport(String planId, TestPlanSimpleReportDTO report) {
|
public void calculatePlanReport(String planId, TestPlanSimpleReportDTO report) {
|
||||||
|
@ -593,11 +593,11 @@ public class TestPlanApiCaseService {
|
||||||
return buildCases(apiTestCases);
|
return buildCases(apiTestCases);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TestPlanFailureApiDTO> getAllCases(Collection<String> caseIdList,String planId,String status) {
|
public List<TestPlanFailureApiDTO> getAllCases(Collection<String> caseIdList, String planId, String status) {
|
||||||
if(caseIdList.isEmpty()){
|
if (caseIdList.isEmpty()) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
List<TestPlanFailureApiDTO> apiTestCases = extTestPlanApiCaseMapper.getFailureListByIds(caseIdList,planId, status);
|
List<TestPlanFailureApiDTO> apiTestCases = extTestPlanApiCaseMapper.getFailureListByIds(caseIdList, planId, status);
|
||||||
return buildCases(apiTestCases);
|
return buildCases(apiTestCases);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,6 +617,7 @@ public class TestPlanApiCaseService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用例自定义排序
|
* 用例自定义排序
|
||||||
|
*
|
||||||
* @param request
|
* @param request
|
||||||
*/
|
*/
|
||||||
public void updateOrder(ResetOrderRequest request) {
|
public void updateOrder(ResetOrderRequest request) {
|
||||||
|
|
Loading…
Reference in New Issue