refactor(测试计划): 测试计划用例列表缺陷弹窗列表

This commit is contained in:
song-cc-rock 2024-08-28 18:23:50 +08:00 committed by Craftsman
parent e755c9de4d
commit c1fd9f7731
14 changed files with 140 additions and 32 deletions

View File

@ -12,6 +12,8 @@ public class TestPlanBugCaseDTO {
private String id;
@Schema(description = "用例业务ID")
private String num;
@Schema(description = "用例类型")
private String type;
@Schema(description = "缺陷ID")
private String bugId;
@Schema(description = "用例名称")

View File

@ -0,0 +1,21 @@
package io.metersphere.plan.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class TestPlanCaseBugDTO {
@Schema(description = "关联关系ID")
private String id;
@Schema(description = "缺陷业务ID")
private String num;
@Schema(description = "缺陷标题")
private String title;
@Schema(description = "缺陷状态")
private String status;
@Schema(description = "计划缺陷关系ID")
private String planCaseRefId;
}

View File

@ -1,10 +1,12 @@
package io.metersphere.plan.dto.response;
import io.metersphere.plan.dto.TestPlanCaseBugDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @author wx
@ -89,4 +91,10 @@ public class TestPlanApiCasePageResponse implements Serializable {
@Schema(description = "更新时间")
private Long updateTime;
@Schema(description = "缺陷数量")
private Integer bugCount;
@Schema(description = "关联的缺陷数据")
private List<TestPlanCaseBugDTO> bugList;
}

View File

@ -1,10 +1,12 @@
package io.metersphere.plan.dto.response;
import io.metersphere.plan.dto.TestPlanCaseBugDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.List;
/**
* @author wx
@ -85,4 +87,10 @@ public class TestPlanApiScenarioPageResponse implements Serializable {
@Schema(description = "更新时间")
private Long updateTime;
@Schema(description = "缺陷数量")
private Integer bugCount;
@Schema(description = "关联的缺陷数据")
private List<TestPlanCaseBugDTO> bugList;
}

View File

@ -1,7 +1,7 @@
package io.metersphere.plan.dto.response;
import io.metersphere.bug.dto.CaseRelateBugDTO;
import io.metersphere.functional.dto.FunctionalCaseCustomFieldDTO;
import io.metersphere.plan.dto.TestPlanCaseBugDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -87,10 +87,10 @@ public class TestPlanCasePageResponse implements Serializable {
private String executeUserName;
@Schema(description = "缺陷数量")
private int bugCount;
private Integer bugCount;
@Schema(description = "关联的缺陷数据")
private List<CaseRelateBugDTO> bugList;
private List<TestPlanCaseBugDTO> bugList;
@Schema(description = "用例的id")
private String caseId;

View File

@ -1,6 +1,7 @@
package io.metersphere.plan.mapper;
import io.metersphere.plan.dto.TestPlanBugCaseDTO;
import io.metersphere.plan.dto.TestPlanCaseBugDTO;
import io.metersphere.plan.dto.request.TestPlanBugPageRequest;
import io.metersphere.plan.dto.response.TestPlanBugPageResponse;
import org.apache.ibatis.annotations.Param;
@ -26,4 +27,11 @@ public interface ExtTestPlanBugMapper {
List<TestPlanBugPageResponse> countBugByIds(@Param("planIds") List<String> planIds);
/**
* 根据用例关系ID集合获取计划下用例关联的缺陷集合
* @param caseIds 用例ID集合
* @return 缺陷集合
*/
List<TestPlanCaseBugDTO> getCaseRelatedBug(@Param("ids") List<String> caseIds);
}

View File

@ -41,10 +41,17 @@
<select id="getBugRelatedCase" resultType="io.metersphere.plan.dto.TestPlanBugCaseDTO">
select brc.case_id as id, fc.num as num, brc.bug_id as bugId, fc.name as name
select brc.case_id as id, fc.num as num, 'FUNCTIONAL' as type, brc.bug_id as bugId, fc.name as name
from bug_relation_case brc
join functional_case fc on brc.case_id = fc.id
<!-- 后续会有其他用例, 根据关联用例类型, 取不同用例表 -->
union
select brc.case_id as id, atc.num as num, 'API' as type, brc.bug_id as bugId, atc.name as name
from bug_relation_case brc
join api_test_case atc on brc.case_id = atc.id
union
select brc.case_id as id, asi.num as num, 'SCENARIO' as type, brc.bug_id as bugId, asi.name as name
from bug_relation_case brc
join api_scenario asi on brc.case_id = asi.id
where brc.test_plan_id = #{planId}
and brc.bug_id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
@ -52,6 +59,16 @@
</foreach>
</select>
<select id="getCaseRelatedBug" resultType="io.metersphere.plan.dto.TestPlanCaseBugDTO">
select brc.id as id, b.num as num, b.title as title, b.status as status, brc.test_plan_case_id as planCaseRefId
from bug_relation_case brc
join bug b on brc.bug_id = b.id
where brc.test_plan_case_id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
<sql id="filters">
<if test="${filter} != null and ${filter}.size() > 0">
<foreach collection="${filter}.entrySet()" index="key" item="values">

View File

@ -243,16 +243,18 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
return new ArrayList<>();
}
List<TestPlanApiCasePageResponse> list = extTestPlanApiCaseMapper.relateApiCaseList(request, deleted);
buildApiCaseResponse(list, request.getTestPlanId());
buildApiCaseResponse(list, request.getTestPlanId(), request.getProjectId());
return list;
}
private void buildApiCaseResponse(List<TestPlanApiCasePageResponse> apiCaseList, String testPlanId) {
private void buildApiCaseResponse(List<TestPlanApiCasePageResponse> apiCaseList, String testPlanId, String projectId) {
if (CollectionUtils.isNotEmpty(apiCaseList)) {
Map<String, String> projectMap = getProject(apiCaseList);
Map<String, String> userMap = getUserMap(apiCaseList);
Map<String, String> moduleNameMap = getModuleName(apiCaseList);
handleCaseAndEnv(apiCaseList, projectMap, userMap, testPlanId, moduleNameMap);
List<String> associateIds = apiCaseList.stream().map(TestPlanApiCasePageResponse::getId).toList();
Map<String, List<TestPlanCaseBugDTO>> associateBugMap = queryCaseAssociateBug(associateIds, projectId);
handleCaseAndEnv(apiCaseList, projectMap, userMap, testPlanId, moduleNameMap, associateBugMap);
}
}
@ -263,7 +265,8 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
.collect(Collectors.toMap(ApiDefinitionModule::getId, ApiDefinitionModule::getName));
}
private void handleCaseAndEnv(List<TestPlanApiCasePageResponse> apiCaseList, Map<String, String> projectMap, Map<String, String> userMap, String testPlanId, Map<String, String> moduleNameMap) {
private void handleCaseAndEnv(List<TestPlanApiCasePageResponse> apiCaseList, Map<String, String> projectMap, Map<String, String> userMap,
String testPlanId, Map<String, String> moduleNameMap, Map<String, List<TestPlanCaseBugDTO>> associateBugMap) {
//获取二级节点环境
List<TestPlanCollectionEnvDTO> secondEnv = extTestPlanCollectionMapper.selectSecondCollectionEnv(CaseType.API_CASE.getKey(), ModuleConstants.ROOT_NODE_PARENT_ID, testPlanId);
Map<String, TestPlanCollectionEnvDTO> secondEnvMap = secondEnv.stream().collect(Collectors.toMap(TestPlanCollectionEnvDTO::getId, item -> item));
@ -289,6 +292,11 @@ public class TestPlanApiCaseService extends TestPlanResourceService {
getRunEnv(collectEnv, caseEnvMap, item);
}
}
if (associateBugMap.containsKey(item.getId())) {
List<TestPlanCaseBugDTO> associateBugs = associateBugMap.get(item.getId());
item.setBugList(associateBugs);
item.setBugCount(associateBugs.size());
}
});
}

View File

@ -382,17 +382,19 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
public List<TestPlanApiScenarioPageResponse> hasRelateApiScenarioList(TestPlanApiScenarioRequest request, boolean deleted) {
filterCaseRequest(request);
List<TestPlanApiScenarioPageResponse> list = extTestPlanApiScenarioMapper.relateApiScenarioList(request, deleted);
buildApiScenarioResponse(list, request.getTestPlanId());
buildApiScenarioResponse(list, request.getTestPlanId(), request.getProjectId());
return list;
}
private void buildApiScenarioResponse(List<TestPlanApiScenarioPageResponse> apiScenarioList, String testPlanId) {
private void buildApiScenarioResponse(List<TestPlanApiScenarioPageResponse> apiScenarioList, String testPlanId, String projectId) {
if (CollectionUtils.isNotEmpty(apiScenarioList)) {
Map<String, String> projectMap = getProject(apiScenarioList);
Map<String, String> userMap = getUserMap(apiScenarioList);
Map<String, String> moduleNameMap = getModuleName(apiScenarioList);
Map<String, String> reportMap = getReportMap(apiScenarioList);
handleScenarioAndEnv(apiScenarioList, projectMap, userMap, testPlanId, moduleNameMap, reportMap);
List<String> associateIds = apiScenarioList.stream().map(TestPlanApiScenarioPageResponse::getId).toList();
Map<String, List<TestPlanCaseBugDTO>> associateBugMap = queryCaseAssociateBug(associateIds, projectId);
handleScenarioAndEnv(apiScenarioList, projectMap, userMap, testPlanId, moduleNameMap, reportMap, associateBugMap);
}
}
@ -415,7 +417,7 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
private void handleScenarioAndEnv(List<TestPlanApiScenarioPageResponse> apiScenarioList, Map<String, String> projectMap,
Map<String, String> userMap, String testPlanId, Map<String, String> moduleNameMap,
Map<String, String> reportMap) {
Map<String, String> reportMap, Map<String, List<TestPlanCaseBugDTO>> associateBugMap) {
//获取二级节点环境
List<TestPlanCollectionEnvDTO> secondEnv = extTestPlanCollectionMapper.selectSecondCollectionEnv(CaseType.SCENARIO_CASE.getKey(), ModuleConstants.ROOT_NODE_PARENT_ID, testPlanId);
Map<String, TestPlanCollectionEnvDTO> secondEnvMap = secondEnv.stream().collect(Collectors.toMap(TestPlanCollectionEnvDTO::getId, item -> item));
@ -442,6 +444,11 @@ public class TestPlanApiScenarioService extends TestPlanResourceService {
getRunEnv(collectEnv, caseEnvMap, item);
}
}
if (associateBugMap.containsKey(item.getId())) {
List<TestPlanCaseBugDTO> associateBugs = associateBugMap.get(item.getId());
item.setBugList(associateBugs);
item.setBugCount(associateBugs.size());
}
});
}

View File

@ -30,7 +30,6 @@ import io.metersphere.plan.dto.*;
import io.metersphere.plan.dto.request.*;
import io.metersphere.plan.dto.response.*;
import io.metersphere.plan.mapper.*;
import io.metersphere.plugin.platform.dto.SelectOption;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.dto.MoveNodeSortDTO;
import io.metersphere.provider.BaseAssociateBugProvider;
@ -260,10 +259,8 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
List<String> ids = functionalCaseLists.stream().map(TestPlanCasePageResponse::getCaseId).collect(Collectors.toList());
Map<String, List<FunctionalCaseCustomFieldDTO>> collect = functionalCaseService.getCaseCustomFiledMap(ids, projectId);
Set<String> userIds = extractUserIds(functionalCaseLists);
List<String> relateIds = functionalCaseLists.stream().map(TestPlanCasePageResponse::getId).collect(Collectors.toList());
Map<String, List<CaseRelateBugDTO>> bugListMap = getBugData(relateIds, functionalCaseLists.getFirst().getTestPlanId());
List<SelectOption> statusOption = bugStatusService.getHeaderStatusOption(projectId);
Map<String, String> statusMap = statusOption.stream().collect(Collectors.toMap(SelectOption::getValue, SelectOption::getText));
List<String> associateIds = functionalCaseLists.stream().map(TestPlanCasePageResponse::getId).toList();
Map<String, List<TestPlanCaseBugDTO>> associateBugMap = queryCaseAssociateBug(associateIds, projectId);
Map<String, String> userMap = userLoginService.getUserNameMap(new ArrayList<>(userIds));
List<String> moduleIds = functionalCaseLists.stream().map(TestPlanCasePageResponse::getModuleId).toList();
List<FunctionalCaseModule> modules = extFunctionalCaseModuleMapper.getNameInfoByIds(moduleIds);
@ -273,10 +270,10 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
testPlanCasePageResponse.setCreateUserName(userMap.get(testPlanCasePageResponse.getCreateUser()));
testPlanCasePageResponse.setExecuteUserName(userMap.get(testPlanCasePageResponse.getExecuteUser()));
testPlanCasePageResponse.setModuleName(StringUtils.isNotBlank(moduleNameMap.get(testPlanCasePageResponse.getModuleId())) ? moduleNameMap.get(testPlanCasePageResponse.getModuleId()) : Translator.get("functional_case.module.default.name"));
if (bugListMap.containsKey(testPlanCasePageResponse.getCaseId())) {
List<CaseRelateBugDTO> bugDTOList = bugListMap.get(testPlanCasePageResponse.getCaseId());
testPlanCasePageResponse.setBugList(handleStatus(bugDTOList, statusMap));
testPlanCasePageResponse.setBugCount(bugDTOList.size());
if (associateBugMap.containsKey(testPlanCasePageResponse.getId())) {
List<TestPlanCaseBugDTO> associateBugs = associateBugMap.get(testPlanCasePageResponse.getId());
testPlanCasePageResponse.setBugList(associateBugs);
testPlanCasePageResponse.setBugCount(associateBugs.size());
}
});
return functionalCaseLists;
@ -290,11 +287,6 @@ public class TestPlanFunctionalCaseService extends TestPlanResourceService {
return bugDTOList;
}
private Map<String, List<CaseRelateBugDTO>> getBugData(List<String> ids, String testPlanId) {
List<CaseRelateBugDTO> bugList = bugRelateCaseMapper.getBugCountByIds(ids, testPlanId);
return bugList.stream().collect(Collectors.groupingBy(CaseRelateBugDTO::getCaseId));
}
public Set<String> extractUserIds(List<TestPlanCasePageResponse> list) {
return list.stream()

View File

@ -4,19 +4,19 @@ import io.metersphere.bug.domain.Bug;
import io.metersphere.bug.domain.BugRelationCase;
import io.metersphere.bug.mapper.BugMapper;
import io.metersphere.bug.mapper.BugRelationCaseMapper;
import io.metersphere.bug.service.BugStatusService;
import io.metersphere.dto.BugProviderDTO;
import io.metersphere.plan.domain.TestPlan;
import io.metersphere.plan.domain.TestPlanCollectionExample;
import io.metersphere.plan.dto.ModuleSelectDTO;
import io.metersphere.plan.dto.TestPlanCollectionDTO;
import io.metersphere.plan.dto.TestPlanResourceAssociationParam;
import io.metersphere.plan.dto.TestPlanResourceExecResultDTO;
import io.metersphere.plan.dto.*;
import io.metersphere.plan.dto.request.BaseCollectionAssociateRequest;
import io.metersphere.plan.dto.request.BasePlanCaseBatchRequest;
import io.metersphere.plan.dto.request.TestPlanCaseAssociateBugRequest;
import io.metersphere.plan.dto.response.TestPlanAssociationResponse;
import io.metersphere.plan.mapper.ExtTestPlanBugMapper;
import io.metersphere.plan.mapper.TestPlanCollectionMapper;
import io.metersphere.plan.mapper.TestPlanMapper;
import io.metersphere.plugin.platform.dto.SelectOption;
import io.metersphere.provider.BaseAssociateBugProvider;
import io.metersphere.request.BugPageProviderRequest;
import io.metersphere.sdk.constants.HttpMethodConstants;
@ -43,6 +43,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Collectors;
//测试计划关联表 通用方法
@Transactional(rollbackFor = Exception.class)
@ -62,6 +63,10 @@ public abstract class TestPlanResourceService extends TestPlanSortService {
private BugRelationCaseMapper bugRelationCaseMapper;
@Resource
private BugMapper bugMapper;
@Resource
private ExtTestPlanBugMapper extTestPlanBugMapper;
@Resource
private BugStatusService bugStatusService;
public static final String MODULE_ALL = "all";
@ -223,4 +228,18 @@ public abstract class TestPlanResourceService extends TestPlanSortService {
}
return null;
}
/**
* 查询(计划关联)用例关联的缺陷
* @param ids 关联用例关系ID集合
* @param projectId 项目ID
* @return 缺陷集合
*/
protected Map<String, List<TestPlanCaseBugDTO>> queryCaseAssociateBug(List<String> ids, String projectId) {
List<TestPlanCaseBugDTO> associateBugs = extTestPlanBugMapper.getCaseRelatedBug(ids);
List<SelectOption> statusOption = bugStatusService.getHeaderStatusOption(projectId);
Map<String, String> statusMap = statusOption.stream().collect(Collectors.toMap(SelectOption::getValue, SelectOption::getText));
associateBugs.forEach(bug -> bug.setStatus(statusMap.get(bug.getStatus())));
return associateBugs.stream().collect(Collectors.groupingBy(TestPlanCaseBugDTO::getPlanCaseRefId));
}
}

View File

@ -49,3 +49,10 @@ VALUES
INSERT INTO `api_definition_module`(`id`, `name`, `parent_id`, `project_id`, `pos`, `create_time`, `update_time`, `update_user`, `create_user`)
VALUES ('123', 'Halo', 'NONE', 'wxx_1234', 384, 1716280762025, 1716280762025, '805048669970432', '805048669970432');
INSERT INTO bug_relation_case (id, case_id, bug_id, case_type, test_plan_id, test_plan_case_id, create_user, create_time, update_time) VALUES
('bug_relate_3', 'wxxx_api_case_1', 'bug_3', 'FUNCTIONAL', 'wxxx_1', 'wxxx_1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('bug_relate_4', 'wxxx_api_case_1', 'bug_4', 'FUNCTIONAL', 'wxxx_1', 'wxxx_1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
INSERT INTO bug (id, num, title, handle_users, handle_user, create_user, create_time,update_user, update_time, delete_user, delete_time, project_id, template_id, platform, status, tags, platform_bug_id, deleted, pos)
VALUES ('bug_3', 100001, 'oasis', 'admin', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, '100001100001', 'bug-template-id', 'Local', 'open', '["default-tag"]', null, 0, 5000);

View File

@ -45,3 +45,10 @@ VALUES
INSERT INTO `api_scenario_module`(`id`, `name`, `pos`, `create_time`, `update_time`, `update_user`, `create_user`, `project_id`, `parent_id`)
VALUES ('wx_scenario_module_123', '测试CSV', 64, 1716196253511, 1716196253511, '714940256100352', '714940256100352', '718255970852864', 'NONE');
INSERT INTO bug_relation_case (id, case_id, bug_id, case_type, test_plan_id, test_plan_case_id, create_user, create_time, update_time) VALUES
('bug_relate_5', 'wxxx_api_scenario_1', 'bug_5', 'FUNCTIONAL', 'wxxx_plan_1', 'wxxx_plan_scenario_1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('bug_relate_6', 'wxxx_api_scenario_1', 'bug_6', 'FUNCTIONAL', 'wxxx_plan_1', 'wxxx_plan_scenario_1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
INSERT INTO bug (id, num, title, handle_users, handle_user, create_user, create_time,update_user, update_time, delete_user, delete_time, project_id, template_id, platform, status, tags, platform_bug_id, deleted, pos)
VALUES ('bug_5', 100001, 'oasis', 'admin', 'admin', 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, 'admin', UNIX_TIMESTAMP() * 1000, '100001100001', 'bug-template-id', 'Local', 'open', '["default-tag"]', null, 0, 5000);

View File

@ -92,3 +92,7 @@ INSERT INTO project_application (project_id, type, type_value) VALUES
INSERT INTO service_integration(`id`, `plugin_id`, `enable`, `configuration`, `organization_id`) VALUES
('621103810617343', 'jira', true, 0x504B0304140008080800BC517657000000000000000000000000030000007A6970258DC10EC2201044FF65CF06D2C498D89347B5574FBD6D8158222CD85D6268E3BF4BE3F5CDBC990DD0DAC531430FB348E65EEBE06B41AAA9289480CC1E4991130D07C022F3A366D7DA13B2373B32261592469AF1572FCF883E289362CB735BF8A4C5EE073474C3CB8E59A6F85EEFF12AE676EC4E67F8FE00504B0708384DA4307800000087000000504B01021400140008080800BC517657384DA43078000000870000000300000000000000000000000000000000007A6970504B0506000000000100010031000000A90000000000, '1'),
('652096294625284', 'zentao', true, 0x504B030414000808080093756458000000000000000000000000030000007A6970AB564A4C49294A2D2E56B252CA282929B0D2D7373437D23334D3333230D033B3B4B230B0B050D2514A4C4ECE2FCD2B01AA4A4CC9CDCC038A1424161797E717A500859C1373F2F3D21D8C0C0C4D811245A985A5A9C525219505A940B900C7108F784F3F377FA55A00504B07088A813510680000006C000000504B01021400140008080800937564588A813510680000006C0000000300000000000000000000000000000000007A6970504B0506000000000100010031000000990000000000, '1');
INSERT INTO bug_relation_case (id, case_id, bug_id, case_type, test_plan_id, test_plan_case_id, create_user, create_time, update_time) VALUES
('bug_relate_1', 'fc_1', 'bug_1', 'FUNCTIONAL', 'plan_1', 'relate_case_1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP),
('bug_relate_2', 'fc_1', 'bug_2', 'FUNCTIONAL', 'plan_1', 'relate_case_1', 'admin', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);