refactor(工作台): 尝试优化查询时间

This commit is contained in:
guoyuqi 2024-12-09 15:35:02 +08:00 committed by Craftsman
parent 06d4d6a79b
commit d5a598b2f9
4 changed files with 111 additions and 30 deletions

View File

@ -48,30 +48,23 @@ import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.project.service.PermissionCheckService;
import io.metersphere.project.service.ProjectApplicationService;
import io.metersphere.project.service.ProjectService;
import io.metersphere.sdk.constants.ExecStatus;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.constants.ResultStatus;
import io.metersphere.sdk.constants.TestPlanConstants;
import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.dto.CombineCondition;
import io.metersphere.sdk.dto.CombineSearch;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.User;
import io.metersphere.system.domain.UserExample;
import io.metersphere.system.domain.UserLayout;
import io.metersphere.system.domain.UserLayoutExample;
import io.metersphere.system.domain.*;
import io.metersphere.system.dto.ProtocolDTO;
import io.metersphere.system.dto.request.schedule.BaseScheduleConfigRequest;
import io.metersphere.system.dto.sdk.OptionDTO;
import io.metersphere.system.dto.user.ProjectUserMemberDTO;
import io.metersphere.system.dto.user.UserExtendDTO;
import io.metersphere.system.mapper.ExtExecTaskItemMapper;
import io.metersphere.system.mapper.ExtSystemProjectMapper;
import io.metersphere.system.mapper.UserLayoutMapper;
import io.metersphere.system.mapper.UserMapper;
import io.metersphere.system.mapper.*;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.ScheduleUtils;
import io.metersphere.system.utils.SessionUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
@ -151,6 +144,10 @@ public class DashboardService {
private ExtTestPlanApiScenarioMapper extTestPlanApiScenarioMapper;
@Resource
private ExtTestPlanBugMapper extTestPlanBugMapper;
@Resource
private TestPlanConfigMapper testPlanConfigMapper;
@Resource
private ScheduleMapper scheduleMapper;
public static final String FUNCTIONAL = "FUNCTIONAL"; // 功能用例
@ -711,41 +708,111 @@ public class DashboardService {
return overViewCountDTO;
}
@NotNull
private TestPlanStatisticsResponse buildStatisticsResponse(String planId, List<TestPlanFunctionalCase> functionalCases, List<TestPlanApiCase> apiCases, List<TestPlanApiScenario> apiScenarios) {
//查出计划
TestPlan testPlan = testPlanMapper.selectByPrimaryKey(planId);
// 计划的更多配置
TestPlanConfig planConfig = this.selectConfig(planId);
//查询定时任务
Schedule schedule = this.selectSchedule(planId);
//构建TestPlanStatisticsResponse
TestPlanStatisticsResponse statisticsResponse = new TestPlanStatisticsResponse();
statisticsResponse.setId(planId);
statisticsResponse.setStatus(testPlan.getStatus());
// 测试计划组没有测试计划配置同理也不用参与用例等数据的计算
if (planConfig != null) {
statisticsResponse.setPassThreshold(planConfig.getPassThreshold());
// 功能用例分组统计开始 (为空时, 默认为未执行)
Map<String, Long> functionalCaseResultCountMap = planStatisticsService.countFunctionalCaseExecResultMap(functionalCases);
// 接口用例分组统计开始 (为空时, 默认为未执行)
Map<String, Long> apiCaseResultCountMap = planStatisticsService.countApiTestCaseExecResultMap(apiCases);
// 接口场景用例分组统计开始 (为空时, 默认为未执行)
Map<String, Long> apiScenarioResultCountMap = planStatisticsService.countApiScenarioExecResultMap(apiScenarios);
// 用例数据汇总
statisticsResponse.setFunctionalCaseCount(CollectionUtils.isNotEmpty(functionalCases) ? functionalCases.size() : 0);
statisticsResponse.setApiCaseCount(CollectionUtils.isNotEmpty(apiCases) ? apiCases.size() : 0);
statisticsResponse.setApiScenarioCount(CollectionUtils.isNotEmpty(apiScenarios) ? apiScenarios.size() : 0);
statisticsResponse.setSuccessCount(planStatisticsService.countCaseMap(functionalCaseResultCountMap, apiCaseResultCountMap, apiScenarioResultCountMap, ResultStatus.SUCCESS.name()));
statisticsResponse.setErrorCount(planStatisticsService.countCaseMap(functionalCaseResultCountMap, apiCaseResultCountMap, apiScenarioResultCountMap, ResultStatus.ERROR.name()));
statisticsResponse.setFakeErrorCount(planStatisticsService.countCaseMap(functionalCaseResultCountMap, apiCaseResultCountMap, apiScenarioResultCountMap, ResultStatus.FAKE_ERROR.name()));
statisticsResponse.setBlockCount(planStatisticsService.countCaseMap(functionalCaseResultCountMap, apiCaseResultCountMap, apiScenarioResultCountMap, ResultStatus.BLOCKED.name()));
statisticsResponse.setPendingCount(planStatisticsService.countCaseMap(functionalCaseResultCountMap, apiCaseResultCountMap, apiScenarioResultCountMap, ExecStatus.PENDING.name()));
statisticsResponse.calculateCaseTotal();
statisticsResponse.calculatePassRate();
statisticsResponse.calculateExecuteRate();
statisticsResponse.calculateTestPlanIsPass();
}
//定时任务
if (schedule != null) {
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()));
}
}
statisticsResponse.calculateCaseTotal();
statisticsResponse.calculatePassRate();
statisticsResponse.calculateExecuteRate();
statisticsResponse.calculateStatus();
statisticsResponse.calculateTestPlanIsPass();
return statisticsResponse;
}
private Schedule selectSchedule(String testPlanId) {
ScheduleExample scheduleExample = new ScheduleExample();
scheduleExample.createCriteria().andResourceIdEqualTo(testPlanId).andResourceTypeEqualTo(ScheduleResourceType.TEST_PLAN.name());
List<Schedule> schedules = scheduleMapper.selectByExample(scheduleExample);
return CollectionUtils.isNotEmpty(schedules) ? schedules.getFirst() : null;
}
private TestPlanConfig selectConfig(String testPlanId) {
return testPlanConfigMapper.selectByPrimaryKey(testPlanId);
}
public OverViewCountDTO projectPlanViewCount(DashboardFrontPageRequest request, String currentUserId) {
OverViewCountDTO overViewCountDTO = new OverViewCountDTO();
String projectId = request.getProjectIds().getFirst();
String planId = request.getPlanId();
if (Boolean.FALSE.equals(permissionCheckService.checkModule(projectId, TEST_PLAN_MODULE, currentUserId, PermissionConstants.TEST_PLAN_READ))) {
overViewCountDTO.setErrorCode(NO_PROJECT_PERMISSION.getCode());
}
if (StringUtils.isBlank(request.getPlanId())) {
if (StringUtils.isBlank(planId)) {
return new OverViewCountDTO(new HashMap<>(), new ArrayList<>(), new ArrayList<>(), 0);
}
List<String> planIds = List.of(request.getPlanId());
List<TestPlanStatisticsResponse> testPlanStatisticsResponses = planStatisticsService.calculateRate(planIds);
TestPlanStatisticsResponse planCount = testPlanStatisticsResponses.getFirst();
List<TestPlanFunctionalCase> planFunctionalCases = extTestPlanFunctionalCaseMapper.getPlanFunctionalCaseByIds(planIds);
List<TestPlanApiCase> planApiCases = extTestPlanApiCaseMapper.getPlanApiCaseByIds(planIds);
List<TestPlanApiScenario> planApiScenarios = extTestPlanApiScenarioMapper.getPlanApiScenarioByIds(planIds);
// 关联的用例数据
List<TestPlanFunctionalCase> planFunctionalCases = extTestPlanFunctionalCaseMapper.selectByTestPlanIdAndNotDeleted(planId);
List<TestPlanApiCase> planApiCases = extTestPlanApiCaseMapper.selectByTestPlanIdAndNotDeleted(planId);
List<TestPlanApiScenario> planApiScenarios = extTestPlanApiScenarioMapper.selectByTestPlanIdAndNotDeleted(planId);
TestPlanStatisticsResponse statisticsResponse = buildStatisticsResponse(planId, planFunctionalCases, planApiCases, planApiScenarios);
// 计划-缺陷的关联数据
List<TestPlanBugPageResponse> planBugs = extTestPlanBugMapper.countBugByIds(planIds);
List<TestPlanBugPageResponse> planBugs = extTestPlanBugMapper.selectBugCountByPlanId(planId);
//获取卡片数据
boolean addDefaultUser = false;
buildCountMap(planCount, planBugs, overViewCountDTO);
buildCountMap(statisticsResponse, planBugs, overViewCountDTO);
List<TestPlanFunctionalCase> caseUserNullList = planFunctionalCases.stream().filter(t -> StringUtils.isBlank(t.getExecuteUser())).toList();
Map<String, List<TestPlanFunctionalCase>> caseUserMap = planFunctionalCases.stream().filter(t->StringUtils.isNotBlank(t.getExecuteUser())).collect(Collectors.groupingBy(TestPlanFunctionalCase::getExecuteUser));
Map<String, List<TestPlanFunctionalCase>> caseUserMap = planFunctionalCases.stream().filter(t -> StringUtils.isNotBlank(t.getExecuteUser())).collect(Collectors.groupingBy(TestPlanFunctionalCase::getExecuteUser));
if (CollectionUtils.isNotEmpty(caseUserNullList)) {
addDefaultUser = true;
caseUserMap.put("NONE", caseUserNullList);
}
List<TestPlanApiCase> apiCaseUserNullList = planApiCases.stream().filter(t -> StringUtils.isBlank(t.getExecuteUser())).toList();
Map<String, List<TestPlanApiCase>> apiCaseUserMap = planApiCases.stream().filter(t->StringUtils.isNotBlank(t.getExecuteUser())).collect(Collectors.groupingBy(TestPlanApiCase::getExecuteUser));
Map<String, List<TestPlanApiCase>> apiCaseUserMap = planApiCases.stream().filter(t -> StringUtils.isNotBlank(t.getExecuteUser())).collect(Collectors.groupingBy(TestPlanApiCase::getExecuteUser));
if (CollectionUtils.isNotEmpty(apiCaseUserNullList)) {
addDefaultUser = true;
apiCaseUserMap.put("NONE", apiCaseUserNullList);
}
List<TestPlanApiScenario> apiScenarioNullList = planApiScenarios.stream().filter(t -> StringUtils.isBlank(t.getExecuteUser())).toList();
Map<String, List<TestPlanApiScenario>> apiScenarioUserMap = planApiScenarios.stream().filter(t->StringUtils.isNotBlank(t.getExecuteUser())).collect(Collectors.groupingBy(TestPlanApiScenario::getExecuteUser));
Map<String, List<TestPlanApiScenario>> apiScenarioUserMap = planApiScenarios.stream().filter(t -> StringUtils.isNotBlank(t.getExecuteUser())).collect(Collectors.groupingBy(TestPlanApiScenario::getExecuteUser));
if (CollectionUtils.isNotEmpty(apiScenarioNullList)) {
addDefaultUser = true;
apiScenarioUserMap.put("NONE", apiScenarioNullList);
@ -785,7 +852,7 @@ public class DashboardService {
String platformName = projectApplicationService.getPlatformName(projectId);
List<SelectOption> headerStatusOption = getStatusOption(projectId, platformName);
List<String> statusList = headerStatusOption.stream().map(SelectOption::getValue).toList();
userNameMap.forEach((userId, name)->{
userNameMap.forEach((userId, name) -> {
int count = 0;
int finishCount = 0;
List<TestPlanFunctionalCase> testPlanFunctionalCases = caseUserMap.get(userId);
@ -871,7 +938,7 @@ public class DashboardService {
int executeRateValue = executeRate == null ? 0 : executeRate.intValue();
caseCountMap.put("executeRate", executeRateValue);
caseCountMap.put("totalCount", planCount.getCaseTotal());
caseCountMap.put("executeCount", planCount.getCaseTotal()-planCount.getPendingCount());
caseCountMap.put("executeCount", planCount.getCaseTotal() - planCount.getPendingCount());
caseCountMap.put(BUG_COUNT, planBugs.size());
List<TestPlan> testPlans = extTestPlanMapper.selectBaseInfoByIds(List.of(planCount.getId()));
caseCountMap.put("testPlanName", testPlans.getFirst().getName());

View File

@ -33,6 +33,9 @@ public interface ExtTestPlanBugMapper {
List<TestPlanBugPageResponse> countBugByIds(@Param("planIds") List<String> planIds);
List<TestPlanBugPageResponse> selectBugCountByPlanId(@Param("planId") String planId);
/**
* 根据用例关系ID集合获取计划下用例关联的缺陷集合
* @param caseIds 用例ID集合

View File

@ -39,6 +39,17 @@
group by brc.bug_id
</select>
<select id="selectBugCountByPlanId" resultType="io.metersphere.plan.dto.response.TestPlanBugPageResponse">
select b.id as id, b.num as num, b.title as title, bc.description content, b.handle_user handleUser, b.status as status, b.create_user createUser, b.create_time createTime,brc.test_plan_id testPlanId
from bug_relation_case brc join bug b on brc.bug_id = b.id
left join bug_content bc on b.id = bc.bug_id
<where>
b.deleted = false
and brc.test_plan_id = #{planId}
</where>
group by brc.bug_id
</select>
<select id="getBugRelatedCase" resultType="io.metersphere.plan.dto.TestPlanBugCaseDTO">
select brc.case_id as id, fc.num as num, 'FUNCTIONAL' as type, brc.bug_id as bugId, fc.name as name, fc.project_id as projectId

View File

@ -178,17 +178,17 @@ public class TestPlanStatisticsService {
return returnResponse;
}
private Map<String, Long> countApiScenarioExecResultMap(List<TestPlanApiScenario> apiScenarios) {
public Map<String, Long> countApiScenarioExecResultMap(List<TestPlanApiScenario> apiScenarios) {
return CollectionUtils.isEmpty(apiScenarios) ? new HashMap<>(16) : apiScenarios.stream().collect(
Collectors.groupingBy(apiScenario -> StringUtils.isEmpty(apiScenario.getLastExecResult()) ? ExecStatus.PENDING.name() : apiScenario.getLastExecResult(), Collectors.counting()));
}
private Map<String, Long> countApiTestCaseExecResultMap(List<TestPlanApiCase> apiCases) {
public Map<String, Long> countApiTestCaseExecResultMap(List<TestPlanApiCase> apiCases) {
return CollectionUtils.isEmpty(apiCases) ? new HashMap<>(16) : apiCases.stream().collect(
Collectors.groupingBy(apiCase -> StringUtils.isEmpty(apiCase.getLastExecResult()) ? ExecStatus.PENDING.name() : apiCase.getLastExecResult(), Collectors.counting()));
}
private Map<String, Long> countFunctionalCaseExecResultMap(List<TestPlanFunctionalCase> functionalCases) {
public Map<String, Long> countFunctionalCaseExecResultMap(List<TestPlanFunctionalCase> functionalCases) {
return CollectionUtils.isEmpty(functionalCases) ? new HashMap<>(16) : functionalCases.stream().collect(
Collectors.groupingBy(functionalCase -> StringUtils.isEmpty(functionalCase.getLastExecResult()) ? ExecStatus.PENDING.name() : functionalCase.getLastExecResult(), Collectors.counting()));
}
@ -277,7 +277,7 @@ public class TestPlanStatisticsService {
* @param countKey 汇总的key
* @return 总数
*/
private Integer countCaseMap(Map<String, Long> functionalCaseMap, Map<String, Long> apiCaseMap, Map<String, Long> apiScenarioMap, String countKey) {
public Integer countCaseMap(Map<String, Long> functionalCaseMap, Map<String, Long> apiCaseMap, Map<String, Long> apiScenarioMap, String countKey) {
return (functionalCaseMap.containsKey(countKey) ? functionalCaseMap.get(countKey).intValue() : 0) +
(apiCaseMap.containsKey(countKey) ? apiCaseMap.get(countKey).intValue() : 0) +
(apiScenarioMap.containsKey(countKey) ? apiScenarioMap.get(countKey).intValue() : 0);