fix(测试计划执行): 更改测试计划执行的细节

更改测试计划执行时的线程顺序为先开启监听线程再开启执行线程、测试计划列表展现时增加结果状态检查
This commit is contained in:
song-tianyang 2021-12-06 18:04:04 +08:00 committed by song-tianyang
parent 516666d381
commit badeee9f20
3 changed files with 121 additions and 40 deletions

View File

@ -322,7 +322,6 @@ public class ApiScenarioReportService {
}
ApiScenarioReport report = editReport(scenarioResult, startTime);
if(report != null){
TestResult newResult = createTestResult(result.getTestId(), scenarioResult);
newResult.setConsole(result.getConsole());
@ -346,26 +345,37 @@ public class ApiScenarioReportService {
} else {
planScenarioId = report.getScenarioId();
}
String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError()));
TestPlanApiScenario testPlanApiScenario = testPlanApiScenarioMapper.selectByPrimaryKey(planScenarioId);
report.setScenarioId(testPlanApiScenario.getApiScenarioId());
report.setTestPlanScenarioId(planScenarioId);
if(testPlanApiScenario != null){
//更新测试计划场景相关状态
report.setScenarioId(testPlanApiScenario.getApiScenarioId());
report.setTestPlanScenarioId(planScenarioId);
if (scenarioResult.getError() > 0) {
scenarioAndErrorMap.put(testPlanApiScenario.getId(), TestPlanApiExecuteStatus.FAILD.name());
testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name());
testPlanApiScenario.setPassRate(passRate);
} else {
scenarioAndErrorMap.put(testPlanApiScenario.getId(), TestPlanApiExecuteStatus.SUCCESS.name());
testPlanApiScenario.setLastResult(ScenarioStatus.Success.name());
}
testPlanApiScenario.setReportId(report.getId());
testPlanApiScenario.setUpdateTime(System.currentTimeMillis());
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
scenarioIdList.add(testPlanApiScenario.getApiScenarioId());
}else {
LogUtil.info("TestPlanReport_Id is null. scenario report id : ["+report.getId()+"]; planScenarioIdArr:["+report.getScenarioId()+"] DATA:"+JSON.toJSONString(scenarioResult));
}
report.setEndTime(System.currentTimeMillis());
apiScenarioReportMapper.updateByPrimaryKeySelective(report);
planScenarioReportMap.put(planScenarioId, report.getId());
if (scenarioResult.getError() > 0) {
scenarioAndErrorMap.put(testPlanApiScenario.getId(), TestPlanApiExecuteStatus.FAILD.name());
testPlanApiScenario.setLastResult(ScenarioStatus.Fail.name());
} else {
scenarioAndErrorMap.put(testPlanApiScenario.getId(), TestPlanApiExecuteStatus.SUCCESS.name());
testPlanApiScenario.setLastResult(ScenarioStatus.Success.name());
}
String passRate = new DecimalFormat("0%").format((float) scenarioResult.getSuccess() / (scenarioResult.getSuccess() + scenarioResult.getError()));
testPlanApiScenario.setPassRate(passRate);
// 报告详情内容
ApiScenarioReportDetail detail = new ApiScenarioReportDetail();
detail.setContent(JSON.toJSONString(newResult).getBytes(StandardCharsets.UTF_8));
detail.setReportId(report.getId());
detail.setProjectId(report.getProjectId());
@ -374,15 +384,11 @@ public class ApiScenarioReportService {
}
apiScenarioReportDetailMapper.insert(detail);
testPlanApiScenario.setReportId(report.getId());
report.setEndTime(System.currentTimeMillis());
testPlanApiScenario.setUpdateTime(System.currentTimeMillis());
testPlanApiScenarioMapper.updateByPrimaryKeySelective(testPlanApiScenario);
scenarioIdList.add(testPlanApiScenario.getApiScenarioId());
scenarioNames.append(report.getName()).append(",");
// 更新场景状态
ApiScenario scenario = apiScenarioMapper.selectByPrimaryKey(testPlanApiScenario.getApiScenarioId());
ApiScenario scenario = apiScenarioMapper.selectByPrimaryKey(report.getScenarioId());
if (scenario != null) {
if (scenarioResult.getError() > 0) {
scenario.setLastResult("Fail");

View File

@ -65,6 +65,8 @@ public class TestPlanReportService {
@Resource
ApiScenarioReportMapper apiScenarioReportMapper;
@Resource
ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
@Resource
TestPlanReportDataMapper testPlanReportDataMapper;
@Resource
ExtTestPlanScenarioCaseMapper extTestPlanScenarioCaseMapper;
@ -126,6 +128,7 @@ public class TestPlanReportService {
}
}
list = extTestPlanReportMapper.list(request);
this.checkReportStatus(list);
return list;
}
@ -612,8 +615,8 @@ public class TestPlanReportService {
testPlanReport.setEndTime(endTime);
testPlanReport.setUpdateTime(endTime);
}
TestPlanReportExecuteCatch.remove(testPlanReport.getId());
testPlanLog.info("Task is finish. Remove listener:" + testPlanReport.getId());
}
testPlanReportContentMapper.updateByPrimaryKeySelective(parseReportDaoToReportContent(reportDTO, reportContent));
@ -1057,7 +1060,9 @@ public class TestPlanReportService {
public synchronized TestPlanReport updateExecuteApis(String planReportId) {
TestPlanExecuteInfo executeInfo = TestPlanReportExecuteCatch.getTestPlanExecuteInfo(planReportId);
if (executeInfo == null) {
return null;
}
Map<String, String> executeApiCaseIdMap = executeInfo.getApiCaseExecInfo();
Map<String, String> executeScenarioCaseIdMap = executeInfo.getApiScenarioCaseExecInfo();
Map<String, String> executePerformanceIdMap = executeInfo.getLoadCaseExecInfo();
@ -1102,17 +1107,11 @@ public class TestPlanReportService {
}
public void countReport(String planReportId) {
TestPlanExecuteInfo executeInfo = TestPlanReportExecuteCatch.getTestPlanExecuteInfo(planReportId);
int unFinishNum = executeInfo.countUnFinishedNum();
if (unFinishNum > 0) {
//如果间隔超过5分钟没有案例执行完成则把执行结果变成false
long lastCountTime = executeInfo.getLastFinishedNumCountTime();
long nowTime = System.currentTimeMillis();
if (nowTime - lastCountTime > 1800000) {
TestPlanReportExecuteCatch.finishAllTask(planReportId);
}
boolean isTimeOut = this.checkTestPlanReportIsTimeOut(planReportId);
if (isTimeOut) {
//判断是否超时超时时强行停止任务
TestPlanReportExecuteCatch.finishAllTask(planReportId);
}
this.updateExecuteApis(planReportId);
}
@ -1172,26 +1171,55 @@ public class TestPlanReportService {
private void updateReportExecResult(TestPlanReportContentWithBLOBs testPlanReportContent) {
boolean isUpdate = false;
boolean isTaskRunning = false;
boolean reportHasData = false;
if (StringUtils.isNotBlank(testPlanReportContent.getApiAllCases())) {
reportHasData = true;
List<TestPlanFailureApiDTO> allCases = JSONObject.parseArray(testPlanReportContent.getApiAllCases(), TestPlanFailureApiDTO.class);
for (TestPlanFailureApiDTO dto : allCases) {
String status = dto.getExecResult();
if (StringUtils.equalsAnyIgnoreCase(status, "Running", "Waiting")) {
isUpdate = true;
ApiDefinitionExecResult definitionExecResult = apiDefinitionExecResultMapper.selectByPrimaryKey(dto.getReportId());
if (definitionExecResult != null) {
dto.setExecResult(definitionExecResult.getStatus());
}
}
if (StringUtils.equalsAnyIgnoreCase(dto.getExecResult(), "Running", "Waiting")) {
isTaskRunning = true;
}
}
testPlanReportContent.setApiAllCases(JSONArray.toJSONString(allCases));
}
if (StringUtils.isNotBlank(testPlanReportContent.getScenarioAllCases())) {
reportHasData = true;
List<TestPlanFailureScenarioDTO> allCases = JSONObject.parseArray(testPlanReportContent.getScenarioAllCases(), TestPlanFailureScenarioDTO.class);
for (TestPlanFailureScenarioDTO dto : allCases) {
if (StringUtils.equalsAnyIgnoreCase("Underway",dto.getStatus(), dto.getLastResult())) {
String lastResult = dto.getLastResult();
if (StringUtils.equalsAnyIgnoreCase(lastResult, "Running", "Waiting", "Underway")) {
isUpdate = true;
ApiScenarioReport apiReport = apiScenarioReportMapper.selectByPrimaryKey(dto.getReportId());
if (apiReport != null) {
dto.setLastResult(apiReport.getStatus());
dto.setStatus(apiReport.getStatus());
}
}else if (StringUtils.equalsAnyIgnoreCase("Error",dto.getStatus(), dto.getLastResult())) {
} else if (StringUtils.equalsAnyIgnoreCase("Error", lastResult)) {
isUpdate = true;
dto.setLastResult("Fail");
dto.setStatus("Fail");
}
if (StringUtils.equalsAnyIgnoreCase(dto.getLastResult(), "Running", "Waiting", "Underway")) {
isTaskRunning = true;
}
}
testPlanReportContent.setScenarioAllCases(JSONArray.toJSONString(allCases));
}
if (StringUtils.isNotBlank(testPlanReportContent.getLoadAllCases())) {
reportHasData = true;
List<TestPlanLoadCaseDTO> allCases = JSONObject.parseArray(testPlanReportContent.getLoadAllCases(), TestPlanLoadCaseDTO.class);
for (TestPlanLoadCaseDTO dto : allCases) {
if (StringUtils.equalsIgnoreCase(dto.getStatus(), "run")) {
@ -1201,12 +1229,20 @@ public class TestPlanReportService {
dto.setStatus(report.getStatus());
}
}
if (StringUtils.equalsAnyIgnoreCase("Underway", dto.getStatus(), dto.getStatus())) {
isTaskRunning = true;
}
}
testPlanReportContent.setLoadAllCases(JSONArray.toJSONString(allCases));
}
if (isUpdate) {
testPlanReportContentMapper.updateByPrimaryKeyWithBLOBs(testPlanReportContent);
}
if (!isTaskRunning && reportHasData) {
this.finishTestPlanReport(testPlanReportContent.getTestPlanReportId());
}
}
public void finishReport(TestPlanReport testPlanReport) {
@ -1215,6 +1251,45 @@ public class TestPlanReportService {
testPlanReport.setUpdateTime(endTime);
testPlanReport.setStatus(TestPlanReportStatus.FAILED.name());
testPlanReportMapper.updateByPrimaryKey(testPlanReport);
testPlanReportMapper.updateByPrimaryKeySelective(testPlanReport);
}
private void checkReportStatus(List<TestPlanReportDTO> list) {
String errorStatus = "FAILED";
for (TestPlanReportDTO dto : list) {
if (StringUtils.equalsIgnoreCase(dto.getStatus(), "Running")) {
if (!TestPlanReportExecuteCatch.containsReport(dto.getId())) {
//测试计划报告处于Running状态且监听中不存在此ID更改Running的运行状态一般在测试计划执行结束之前服务关闭时会出现这种情况
TestPlanReport report = new TestPlanReport();
report.setId(dto.getId());
this.finishReport(report);
dto.setStatus(errorStatus);
}
}
}
}
private boolean checkTestPlanReportIsTimeOut(String planReportId) {
TestPlanExecuteInfo executeInfo = TestPlanReportExecuteCatch.getTestPlanExecuteInfo(planReportId);
int unFinishNum = executeInfo.countUnFinishedNum();
if (unFinishNum > 0) {
//15分钟没有案例执行结果更新则定位超时
long lastCountTime = executeInfo.getLastFinishedNumCountTime();
long nowTime = System.currentTimeMillis();
if (nowTime - lastCountTime > 9000) {
return true;
}
}
return false;
}
private void finishTestPlanReport(String planReportId) {
TestPlanReport testPlanReport = testPlanReportMapper.selectByPrimaryKey(planReportId);
if (testPlanReport != null && StringUtils.equalsIgnoreCase("Running", testPlanReport.getStatus())) {
this.finishReport(testPlanReport);
testPlanLog.info("结束测试计划报告:[" + planReportId + "]");
}
TestPlanReportExecuteCatch.remove(planReportId);
}
}

View File

@ -190,7 +190,7 @@ public class TestPlanService {
@Resource
private TestPlanFollowMapper testPlanFollowMapper;
private final ExecutorService executorService = Executors.newFixedThreadPool(20, new NamedThreadFactory("TestPlanService"));
private final ExecutorService executorService = Executors.newFixedThreadPool(40, new NamedThreadFactory("TestPlanService"));
public synchronized TestPlan addTestPlan(AddTestPlanRequest testPlan) {
if (getTestPlanByName(testPlan.getName()).size() > 0) {
@ -1125,11 +1125,13 @@ public class TestPlanService {
extTestPlanMapper.updateActualEndTimeIsNullById(testPlanID);
String planReportId = testPlanReport.getId();
testPlanLog.info("ReportId[" + planReportId + "] created. TestPlanID:[" + testPlanID + "]. " + "API Run Config:【" + apiRunConfig + "");
//开启测试计划执行状态的监听
this.listenTaskExecuteStatus(planReportId);
//不同任务的执行ID
Map<String, String> executePerformanceIdMap = new HashMap<>();
Map<String, String> executeApiCaseIdMap = new HashMap<>();
Map<String, String> executeScenarioCaseIdMap = new HashMap<>();
//执行性能测试任务
Map<String, String> performaneReportIDMap = new LinkedHashMap<>();
Map<String, String> performaneThreadIDMap = new LinkedHashMap<>();
@ -1193,7 +1195,6 @@ public class TestPlanService {
this.executeApiTestCase(triggerMode, planReportId, new ArrayList<>(planApiCaseMap.keySet()), runModeConfig);
//执行场景执行任务
this.executeScenarioCase(planReportId, testPlanID, projectID, runModeConfig, triggerMode, userId, planScenarioIdsMap);
this.listenTaskExecuteStatus(planReportId);
return testPlanReport.getId();
}
@ -1207,6 +1208,7 @@ public class TestPlanService {
Thread.sleep(10000);
}
} catch (InterruptedException e) {
TestPlanReportExecuteCatch.remove(planReportId);
e.printStackTrace();
}
});
@ -1215,8 +1217,6 @@ public class TestPlanService {
private void executeApiTestCase(String triggerMode, String planReportId, List<String> planCaseIds, RunModeConfig runModeConfig) {
executorService.submit(() -> {
BatchRunDefinitionRequest request = new BatchRunDefinitionRequest();
// List<String> planIdList = new ArrayList<>(1);
// planIdList.add(testPlanId);
if (StringUtils.equals(triggerMode, ReportTriggerMode.API.name())) {
request.setTriggerMode(ApiRunMode.JENKINS_API_PLAN.name());
} else if (StringUtils.equals(triggerMode, ReportTriggerMode.MANUAL.name())) {