refactor(测试计划): 修改测试计划统计查询方法,增加定时任务的查询
This commit is contained in:
parent
051b3acbdd
commit
63168b9067
|
@ -19,10 +19,8 @@ import io.metersphere.api.parser.step.StepParser;
|
|||
import io.metersphere.api.parser.step.StepParserFactory;
|
||||
import io.metersphere.api.service.ApiCommonService;
|
||||
import io.metersphere.api.service.ApiFileResourceService;
|
||||
import io.metersphere.api.service.definition.ApiDefinitionModuleService;
|
||||
import io.metersphere.api.service.definition.ApiDefinitionService;
|
||||
import io.metersphere.api.service.definition.ApiTestCaseService;
|
||||
import io.metersphere.api.service.queue.ApiExecutionSetService;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.api.utils.ApiScenarioBatchOperationUtils;
|
||||
import io.metersphere.functional.domain.FunctionalCaseTestExample;
|
||||
|
@ -65,6 +63,7 @@ import io.metersphere.system.service.OperationHistoryService;
|
|||
import io.metersphere.system.service.UserLoginService;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import io.metersphere.system.uid.NumGenerator;
|
||||
import io.metersphere.system.utils.ScheduleUtils;
|
||||
import io.metersphere.system.utils.ServiceUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
@ -79,10 +78,6 @@ import org.apache.ibatis.session.ExecutorType;
|
|||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.quartz.CronExpression;
|
||||
import org.quartz.CronScheduleBuilder;
|
||||
import org.quartz.CronTrigger;
|
||||
import org.quartz.TriggerBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
@ -242,7 +237,7 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
}
|
||||
item.setScheduleConfig(request);
|
||||
if (schedule.getEnable()) {
|
||||
item.setNextTriggerTime(getNextTriggerTime(schedule.getValue()));
|
||||
item.setNextTriggerTime(ScheduleUtils.getNextTriggerTime(schedule.getValue()));
|
||||
}
|
||||
}
|
||||
if (MapUtils.isNotEmpty(reportMap) && reportMap.containsKey(item.getLastReportId())) {
|
||||
|
@ -251,22 +246,6 @@ public class ApiScenarioService extends MoveNodeService {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下次执行时间(getFireTimeAfter,也可以下下次...)
|
||||
*
|
||||
* @param cron cron表达式
|
||||
* @return 下次执行时间
|
||||
*/
|
||||
private static Long getNextTriggerTime(String cron) {
|
||||
if (!CronExpression.isValidExpression(cron)) {
|
||||
return null;
|
||||
}
|
||||
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("Calculate Date").withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
|
||||
Date time0 = trigger.getStartTime();
|
||||
Date time1 = trigger.getFireTimeAfter(time0);
|
||||
return time1 == null ? 0 : time1.getTime();
|
||||
}
|
||||
|
||||
private Set<String> extractUserIds(List<ApiScenarioDTO> list) {
|
||||
return list.stream()
|
||||
.flatMap(apiScenario -> Stream.of(apiScenario.getUpdateUser(), apiScenario.getDeleteUser(), apiScenario.getCreateUser()))
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package io.metersphere.system.utils;
|
||||
|
||||
|
||||
import org.quartz.CronExpression;
|
||||
import org.quartz.CronScheduleBuilder;
|
||||
import org.quartz.CronTrigger;
|
||||
import org.quartz.TriggerBuilder;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class ScheduleUtils {
|
||||
/**
|
||||
* 获取下次执行时间(getFireTimeAfter,也可以下下次...)
|
||||
*
|
||||
* @param cron cron表达式
|
||||
* @return 下次执行时间
|
||||
*/
|
||||
public static Long getNextTriggerTime(String cron) {
|
||||
if (!CronExpression.isValidExpression(cron)) {
|
||||
return null;
|
||||
}
|
||||
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("Calculate Date").withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
|
||||
Date time0 = trigger.getStartTime();
|
||||
Date time1 = trigger.getFireTimeAfter(time0);
|
||||
return time1 == null ? 0 : time1.getTime();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package io.metersphere.plan.dto.response;
|
|||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import io.metersphere.plan.serializer.CustomRateSerializer;
|
||||
import io.metersphere.system.dto.request.schedule.BaseScheduleConfigRequest;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
@ -55,4 +56,8 @@ public class TestPlanStatisticsResponse {
|
|||
private Integer apiScenarioCount = 0;
|
||||
@Schema(description = "缺陷数量")
|
||||
private Integer bugCount = 0;
|
||||
@Schema(description = "定时任务配置")
|
||||
private BaseScheduleConfigRequest scheduleConfig;
|
||||
@Schema(description = "定时任务下一次执行时间")
|
||||
private Long nextTriggerTime;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@ import io.metersphere.plan.mapper.ExtTestPlanFunctionalCaseMapper;
|
|||
import io.metersphere.plan.mapper.TestPlanConfigMapper;
|
||||
import io.metersphere.plan.utils.RateCalculateUtils;
|
||||
import io.metersphere.sdk.constants.ExecStatus;
|
||||
import io.metersphere.sdk.constants.ScheduleResourceType;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.domain.Schedule;
|
||||
import io.metersphere.system.domain.ScheduleExample;
|
||||
import io.metersphere.system.dto.request.schedule.BaseScheduleConfigRequest;
|
||||
import io.metersphere.system.mapper.ScheduleMapper;
|
||||
import io.metersphere.system.utils.ScheduleUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -29,6 +36,8 @@ public class TestPlanStatisticsService {
|
|||
private ExtTestPlanFunctionalCaseMapper extTestPlanFunctionalCaseMapper;
|
||||
@Resource
|
||||
private ExtTestPlanBugMapper extTestPlanBugMapper;
|
||||
@Resource
|
||||
private ScheduleMapper scheduleMapper;
|
||||
|
||||
/**
|
||||
* 计划的用例统计数据
|
||||
|
@ -83,6 +92,13 @@ public class TestPlanStatisticsService {
|
|||
// 计划-功能用例的关联数据
|
||||
List<TestPlanFunctionalCase> planFunctionalCases = extTestPlanFunctionalCaseMapper.getPlanFunctionalCaseByIds(planIds);
|
||||
Map<String, List<TestPlanFunctionalCase>> planFunctionalCaseMap = planFunctionalCases.stream().collect(Collectors.groupingBy(TestPlanFunctionalCase::getTestPlanId));
|
||||
|
||||
//查询定时任务
|
||||
ScheduleExample scheduleExample = new ScheduleExample();
|
||||
scheduleExample.createCriteria().andResourceIdIn(planIds).andResourceTypeEqualTo(ScheduleResourceType.TEST_PLAN.name());
|
||||
List<Schedule> schedules = scheduleMapper.selectByExample(scheduleExample);
|
||||
Map<String, Schedule> scheduleMap = schedules.stream().collect(Collectors.toMap(Schedule::getResourceId, t -> t));
|
||||
|
||||
// TODO: 计划-接口用例的关联数据
|
||||
planIds.forEach(planId -> {
|
||||
TestPlanStatisticsResponse statisticsResponse = new TestPlanStatisticsResponse();
|
||||
|
@ -115,6 +131,23 @@ public class TestPlanStatisticsService {
|
|||
statisticsResponse.setPassRate(RateCalculateUtils.divWithPrecision(statisticsResponse.getSuccessCount(), statisticsResponse.getCaseTotal(), 2));
|
||||
statisticsResponse.setExecuteRate(RateCalculateUtils.divWithPrecision(statisticsResponse.getCaseTotal() - statisticsResponse.getPendingCount(), statisticsResponse.getCaseTotal(), 2));
|
||||
planStatisticsResponses.add(statisticsResponse);
|
||||
|
||||
//定时任务
|
||||
if (scheduleMap.containsKey(planId)) {
|
||||
Schedule schedule = scheduleMap.get(planId);
|
||||
BaseScheduleConfigRequest request = new BaseScheduleConfigRequest();
|
||||
request.setEnable(schedule.getEnable());
|
||||
request.setCron(schedule.getValue());
|
||||
request.setResourceId(planId);
|
||||
if (schedule.getConfig() != null) {
|
||||
request.setRunConfig(JSON.parseObject(schedule.getConfig(), Map.class));
|
||||
}
|
||||
statisticsResponse.setScheduleConfig(request);
|
||||
if (schedule.getEnable()) {
|
||||
statisticsResponse.setNextTriggerTime(ScheduleUtils.getNextTriggerTime(schedule.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
return planStatisticsResponses;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import io.metersphere.plan.domain.*;
|
|||
import io.metersphere.plan.dto.request.*;
|
||||
import io.metersphere.plan.dto.response.TestPlanOperationResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanResponse;
|
||||
import io.metersphere.plan.dto.response.TestPlanStatisticsResponse;
|
||||
import io.metersphere.plan.mapper.ExtTestPlanMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanMapper;
|
||||
import io.metersphere.plan.mapper.TestPlanReportMapper;
|
||||
|
@ -1365,10 +1366,23 @@ public class TestPlanTests extends BaseTest {
|
|||
this.requestGet(String.format(URL_POST_TEST_PLAN_SCHEDULE_DELETE, groupTestPlanId7)).andExpect(status().is5xxServerError());
|
||||
//恢复
|
||||
testPlanTestService.resetProjectModule(project, PROJECT_MODULE);
|
||||
|
||||
//正是测试
|
||||
MvcResult result = this.requestPostAndReturn(URL_POST_TEST_PLAN_SCHEDULE, request);
|
||||
ResultHolder resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class);
|
||||
String scheduleId = resultHolder.getData().toString();
|
||||
testPlanTestService.checkSchedule(scheduleId, groupTestPlanId7, request.isEnable());
|
||||
//检查统计接口查询的是否正确
|
||||
List<TestPlanStatisticsResponse> statisticsResponses = JSON.parseArray(
|
||||
JSON.toJSONString(
|
||||
JSON.parseObject(
|
||||
this.requestPostAndReturn(URL_POST_TEST_PLAN_STATISTICS, List.of(groupTestPlanId7))
|
||||
.getResponse().getContentAsString(), ResultHolder.class).getData()),
|
||||
TestPlanStatisticsResponse.class);
|
||||
Assertions.assertTrue(statisticsResponses.size() == 1);
|
||||
Assertions.assertTrue(statisticsResponses.getFirst().getNextTriggerTime() > 0);
|
||||
Assertions.assertTrue(statisticsResponses.getFirst().getScheduleConfig().isEnable());
|
||||
|
||||
|
||||
//增加日志检查
|
||||
LOG_CHECK_LIST.add(
|
||||
|
@ -1383,6 +1397,17 @@ public class TestPlanTests extends BaseTest {
|
|||
//检查两个scheduleId是否相同
|
||||
Assertions.assertEquals(scheduleId, newScheduleId);
|
||||
testPlanTestService.checkSchedule(newScheduleId, groupTestPlanId7, request.isEnable());
|
||||
//检查统计接口查询的是否正确
|
||||
statisticsResponses = JSON.parseArray(
|
||||
JSON.toJSONString(
|
||||
JSON.parseObject(
|
||||
this.requestPostAndReturn(URL_POST_TEST_PLAN_STATISTICS, List.of(groupTestPlanId7))
|
||||
.getResponse().getContentAsString(), ResultHolder.class).getData()),
|
||||
TestPlanStatisticsResponse.class);
|
||||
Assertions.assertTrue(statisticsResponses.size() == 1);
|
||||
Assertions.assertTrue(statisticsResponses.getFirst().getNextTriggerTime() == null);
|
||||
Assertions.assertFalse(statisticsResponses.getFirst().getScheduleConfig().isEnable());
|
||||
|
||||
|
||||
//测试各种corn表达式用于校验正则的准确性
|
||||
String[] cornStrArr = new String[]{
|
||||
|
@ -1451,6 +1476,16 @@ public class TestPlanTests extends BaseTest {
|
|||
//测试删除
|
||||
this.requestGetWithOk(String.format(URL_POST_TEST_PLAN_SCHEDULE_DELETE, groupTestPlanId7));
|
||||
testPlanTestService.checkScheduleIsRemove(groupTestPlanId7);
|
||||
//检查统计接口查询的是否正确
|
||||
statisticsResponses = JSON.parseArray(
|
||||
JSON.toJSONString(
|
||||
JSON.parseObject(
|
||||
this.requestPostAndReturn(URL_POST_TEST_PLAN_STATISTICS, List.of(groupTestPlanId7))
|
||||
.getResponse().getContentAsString(), ResultHolder.class).getData()),
|
||||
TestPlanStatisticsResponse.class);
|
||||
Assertions.assertTrue(statisticsResponses.size() == 1);
|
||||
Assertions.assertTrue(statisticsResponses.getFirst().getNextTriggerTime() == null);
|
||||
Assertions.assertTrue(statisticsResponses.getFirst().getScheduleConfig() == null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue